/**
 * @version	1.3.4b
 *   Change Log:
 *    - 0.6.0: Original Version : Jung-Jae Kim
 *    - 0.6.1: Updated BlackBerry Send SMS function to support sending multi-SMS : Bart
 *    - 0.6.1a: Adding template for Global Preference class : Jung-Jae Kim
 *    - 0.6.2: Updated Android Global preference functions and application functions : Jung-Jae Kim
 *    - 0.6.3: Update BlackBerry Global preferences and some application stuff : Bart
 *    - 0.6.3a: Merge from Bart and JJ Kim, add semicolons at the end of each function : JJ
 *    - 0.6.4: Updated Android application functions : JJ
 *    - 0.6.5: Updated iPhone application functions : SY Jang
 *    - 0.6.5a: Fixed bug on application.exitWithResult when no data returned : J.J. Kim
 *    - 0.6.6: Add simulator branch : J.J. Kim
 *    - 0.6.7: Changed BB HTTP function, **type passing to delegator(in progress)** : Bart
 *    - 0.7.0: Added GeoLocation, Camera classes and some functions to Contant : J.J. Kim
 *    - 0.7.1: Added contact functions : J.J. Kim
 *    - 0.7.2: Small Change in Progress Bar to add custom messages (used w/widget functions) : Bart
 *    - 0.7.3: Added and implemented GeoLocation class for Android : J.J. Kim
 *    - 0.7.4: Added and implemented Camera class for Android : J.J. Kim
 *    - 0.7.5: Added & Implemented Blackberry Application Run, Camera, and GPS : Bart
 *    - 0.7.6: Added BB contact & some bug fixes : Bart
 *    - 0.8.0: Fixed window height bug when it is loaded first time on Android : J.J. Kim : related vertion of Android = 0.8
 *    - 0.8.1: Additional information for Camera : J.J. Kim : related vertion of Android = 0.8a
 *    - 0.8.2: Camera, GeoLocation, Contact : Seyoung Jang
 *    - 0.8.3: GlobalPreferences/Preferences update (check iPhone plz!): Bart
 *    - 0.8.4: native extenstion add: Seyoung Jang
 *    - 0.8.5: Debuged some bug on alopexController.back and added device.getWindowHeight function : J.J. Kim
 *    - 0.9.0: Fixed some problem in Preference : J.J. Kim
 *    - 1.0.0: relaese
 *    - 1.0.1: Changed http.requestPostBody for authentication : J.J. Kim
 *    - 1.0.2: Added BlackBerry http authentication : Bart
 *    - 1.0.3: Updated BlackBerry native extension  : Bart
 *    - 1.0.4: Added Android Sensor : J.J. Kim
 *    - 1.0.5a: Changed simulator conditions. window.isSimulator : Leemin
 *    - 1.1.0: BlackBerry Sensor : Bart
 *    - 1.2.0: BlackBerry added HTTP Headers for CIP : Bart
 *    - 1.2.1: Android added some blocking login in http request : J.J. Kim
 *    - 1.3.0: Android added file upload function for http : J.J. Kim
 *    - 1.3.1: Update iPhone function: Seyoung Jang
 *    - 1.3.2: Android setCustomizedBack function is modified : J.J. Kim
 *    - 1.3.2: Added AlopexController.navigateWithUrl for Android : J.J. Kim
 *    - 1.3.3b: Relaesed : J.J. Kim
 *    - 1.3.4: Added http.setTimeout, alopexController.setOnPause and setOnDestroy, and notification methods : J.J. Kim
 *    - 1.3.4b: Added device.getWindowWidth and device.getOrientation methods for Android : J.J. Kim
 * */

var _anomFunkMap = {};
var _anomFunkMapNextId = 0;

function anomToNameFunk(fun) {
	var funkId = "f" + _anomFunkMapNextId++;
	var funk = function() {
		_anomFunkMap[funkId].apply(this, arguments);
		_anomFunkMap[funkId] = null;
		
		delete _anomFunkMap[funkId];
	};
	
	_anomFunkMap[funkId] = funk;
	
	return "_anomFunkMap." + funkId;
}

//inner function은 이름이 정상적으로 나오지 않으므로 callback function은 inner로 정의하지 않음 
function GetFunctionName(fn) {
	if(fn) {
		var m = fn.toString().match(/^\s*function\s+([^\s\(]+)/);
		
		return m ? m[1] : anomToNameFunk(fn);
	}
	else
		return null;
}

if(typeof(DeviceInfo) != 'object')
	DeviceInfo = {};

//This represents the AlopexGap API itself, and provides a global namespace for accessing information about the state of AlopexGap.
/**
 * AlopexGap는 Alopex Framework Javascrit API가 사용될 수 있도록 설정해 주는 클래스. 
 * @constructor
 */
AlopexGap = {
	queue: {
		ready: true,
		commands: [],
		timer: null
	}, _constructors: []
};

/**
 * AlopexGap이 초기화되고 사용가능한지 나타낸트 Boolean 값
 * @members
 */ // TODO: Remove this, it is unused here ... -jm
AlopexGap.available = DeviceInfo.uuid != undefined;

/**
 * Add an initialization function to a queue that ensures it will run and initialize
 * application constructors only once AlopexGap has been initialized.
 * @param {Function} func The function callback you want run once AlopexGap is initialized
 */

onload = function() { document.readyState = "loaded"; };

/**
 * 실행시킬 함수를 스택에 저장한 후 실행가능할 때 실행한다.
 * @param function 실행시킬 함수
 */
AlopexGap.addConstructor = function(func) {
	var state = document.readyState;
	var android = true;
	
	try {
		deviceD;
	} catch(e) {
		android = false;
	}
	
	if((state == 'loaded' || state == 'complete') && ((!android && DeviceInfo.uuid != null) || android)) // Android
		func();
	else
		AlopexGap._constructors.push(func); // iPhone, blackberry
};

(function() {
	var timer = setInterval(function() {
		var state = document.readyState;
		var androidOrBlackBerry = true;
		
		try {
			deviceD;
		} catch(e) {
			androidOrBlackBerry = false;
		}
		
		if((state == 'loaded' || state == 'complete') && ((!androidOrBlackBerry && DeviceInfo.uuid != null) || androidOrBlackBerry)) {
			clearInterval(timer); // stop looking
			// run our constructors list
			while(AlopexGap._constructors.length > 0) {
				var constructor = AlopexGap._constructors.shift();
				
				if(window.isSimulator){
					constructor();
				}else{
					try {
						constructor();
					} catch(e) {
						if(typeof(debug)!="undefined" && typeof(debug['log']) == 'function')
							debug.log("Failed to run constructor: " + debug.processMessage(e));
						else
							log.error("Failed to run constructor: " + e.message + e);
					}
				}
			}
			
			// all constructors run, now fire the deviceready event
			var e = document.createEvent('Events');
			e.initEvent('deviceready', true, true);
			document.dispatchEvent(e);
		}
	}, 1);
})();

/**
 * Execute a AlopexGap command in a queued fashion, to ensure commands do not
 * execute with any race conditions, and only run when AlopexGap is ready to
 * recieve them.
 * @private
 * @param {String} command Command to be run in AlopexGap, e.g. "ClassName.method"
 * @param {String[]} [args] Zero or more arguments to pass to the method
 */
AlopexGap.exec = function() {
	AlopexGap.queue.commands.push(arguments);
	
	if(AlopexGap.queue.timer == null)
		AlopexGap.queue.timer = setInterval(AlopexGap.run_command, 10);
};

/**
 * Internal function used to dispatch the request to AlopexGap.  It processes the
 * command queue and executes the next command on the list.  If one of the
 * arguments is a JavaScript object, it will be passed on the QueryString of the
 * url, which will be turned into a dictionary on the other end.
 * @private
 */
AlopexGap.run_command = function() {
	if(!AlopexGap.available || !AlopexGap.queue.ready)
		return;
	
	AlopexGap.queue.ready = false;
	
	var args = AlopexGap.queue.commands.shift();
	
	if(AlopexGap.queue.commands.length == 0) {
		clearInterval(AlopexGap.queue.timer);
		AlopexGap.queue.timer = null;
	}
	
	var uri = [];
	var dict = null;
	
	for(var i = 1; i < args.length; i++) {
		var arg = args[i];
		
		if(arg == undefined || arg == null)
			arg = '';
		if(typeof(arg) == 'object')
			dict = arg;
		else
			uri.push(encodeURIComponent(arg));
	}
	
	var url = "gap://" + args[0] + "/" + uri.join("/");
	
	if(dict != null) {
		var query_args = [];
		
		for(var name in dict) {
			if(typeof(name) != 'string')
				continue;
			
			query_args.push(encodeURIComponent(name) + "=" + encodeURIComponent(dict[name]));
		}
		
		if(query_args.length > 0)
			url += "?" + query_args.join("&");
	}
	
	document.location = url;
};

/**
 * Device(스마트폰)의 속성들을 가져올 수 있는 클래스
 * 
 * getDeviceId, getPhoneNumber 함수는 추가가 필요함
 * 
 * @constructor
 */
function Device() {
	/**
	 * 현재 작동되는 Alopex javascript와 Runtime의 버전
	 * @members
	 */
	this.alopexVersion  = null;
	/**
	 * 플랫폼 os의 버전
	 * @members
	 */
	this.osVersion = null;
	/**
	 * 플랫폼 전체 이름 ex) iPhone 4.2, Android 2.1 등
	 * @members
	 */
	this.platform = null;
	/**
	 * 플랫폼 전체 이름 중에서 버전을 제외한 순수 이름
	 * ex) iPhone, Android
	 * @members
	 */
	this.platformName = null;
	/**
	 * 단말기의 uuid (식별자)
	 * @members
	 */
	this.uuid = null;
	
	// For Android
	try {
		this.alopexVersion = deviceD.getAlopexVersion() + "";
		this.osVersion = deviceD.getOSVersion() + "";
		this.platform = deviceD.getPlatform() + "";
		this.uuid = deviceD.getUUID() + "";
		this.locale = deviceD.getLocale().toLowerCase() + "";
	} catch(e) {}
	
	// For iPhone
	if(this.platform == null) {
		try {
			this.alopexVersion = DeviceInfo.alopexVersion;
			this.osVersion = DeviceInfo.version;
			this.platform = DeviceInfo.platform;
			this.uuid = DeviceInfo.uuid;
			this.locale = DeviceInfo.locale;
		} catch(e) {}
	}

	// For BlackBerry	
	if(this.platform == null) {
		try {
			this.alopexVersion = deviceD.alopexVersion;
			this.osVersion = deviceD.osVersion;
			this.platform = deviceD.platformName;
			this.uuid = deviceD.uuid;
			this.deviceId = deviceD.platform;
			this.phoneNumber = deviceD.phoneNumber;
		} catch(e) {}
	}

	
	if(this.platform != null && this.platform.indexOf("Android") != -1) {
		this.platformName = "Android";
		
		window.innerHeight = deviceD.getHtmlHeight();
		try {
			window.innerWidth = deviceD.getHtmlWidth();
		} catch(e) {}
	}
	else if(this.platform != null && this.platform.indexOf("BlackBerry") != -1)
		this.platformName = "BlackBerry";
	else if(this.platform != null && (this.platform.indexOf("iPhone") != -1 || this.platform.indexOf("iPad") != -1))
		this.platformName = "iPhone";
	else if(this.platform != null && this.platform.indexOf("simulator") != -1)
		this.platformName = "simulator";
	
	/**
	 * 현재 alopex framework가 초기화 되어 사용가능 한지 여부
	 * @members
	 */
	this.available = AlopexGap.available = this.uuid != null;
}

Device.prototype.getWindowHeight = function getWindowHeight() {
	if(this.platformName == "Android")
		return deviceD.getHtmlHeight();
	
	return window.innerHeight;
};

Device.prototype.getWindowWidth = function getWindowWidth() {
	if(this.platformName == "Android")
		return deviceD.getHtmlWidth();
	
	return window.innerWidth;
};

Device.prototype.getOrientation = function getOrientation() {
	if(this.platformName == "Android")
		return deviceD.getOrientation();
	
	// TODO : for iphone, it need to be implemented
	return undefined;
};

var device;

AlopexGap.addConstructor(function() {
	device = window.device = new Device();
});
// Device Class End


/**
 * AlopexController Class Start
 * 화면 흐름에 관련된 함수가 정의된 클래스
 * @constructor
 * TODO getDeviceId, getPhoneNumber 함수는 추가가 필요함(iPhone, Android 공통)
 * TODO Android currentPage 안가지고 있음
 */
function AlopexController() {
	if(device.platformName == "Android" || window.isSimulator || device.platformName == "BlackBerry") {
		this.parameters = new Array();
		this.customizedBack = null;
	}
	else if(device.platformName == "iPhone" && !window.isSimulator) {
		this.parameters = new Array();
		this.initHandler = null;
		this.currentPage = null;
	}
}

/**
 * 이전 페이지로 돌아가기
 * @param steps 돌아갈 페이지 수
 * 
 */
AlopexController.prototype.back = function back(steps) {
	if(steps == null || steps == undefined || isNaN(steps) || steps >= 0) {
		var errorMessage = "Alopex Error : Invalid argument";
		
		log.error(errorMessage);
		alert(errorMessage);
		
		return;
	}
	
	if(device.platformName == "Android" || window.isSimulator || device.platformName == "BlackBerry")
		alopexControllerD.back(parseInt(steps, 10));
	else if(device.platformName == "iPhone" && !window.isSimulator)
		AlopexGap.exec("Alopex.back", steps);
};

/**
 * 프로그램 종료합니다.
 * 
 * @function
 */
AlopexController.prototype.exit = function exit() {
	if(device.platformName == "Android" || window.isSimulator || device.platformName == "BlackBerry")
		alopexControllerD.exit();
	else if(device.platformName == "iPhone" && !window.isSimulator)
		AlopexGap.exec("Alopex.exit");
};

/**
 * 다른 앱에서 지금 앱을 실행시킨 경우 결과값 데이터를 가지고 프로그램을 종료시킵니다. 
 * @param params caller 앱에 전송할 데이터
 */
AlopexController.prototype.exitWithResult = function exitWithResult(params) {
	if(device.platformName == "Android" || window.isSimulator) {
		var query = [];
		
		for(var name in params)
			query.push(name + "=" + escape(params[name]));
		
		if(query.length != 0)
			alopexControllerD.exitWithResult(query.join("&"));
		else
			alopexControllerD.exit();
	}
	else if(device.platformName == "BlackBerry") {
		var query = [];
		
		for(var name in params)
			query.push(name + "=" + escape(params[name]));
		
		if(query.length != 0)
			alopexControllerD.exitWithResult(query.join("&"));
		else
			alopexControllerD.exit();
	}
	else if(device.platformName == "iPhone" && !window.isSimulator)
		AlopexGap.exec("Alopex.exitWithResult", params);
};

/**
 * Parameters의 개수를 리턴합니다.
 * @return int Parameters의 개수
 */
AlopexController.prototype.getParameterSize = function getParameterSize() {
	if(this.parameters == undefined || this.parameters == null)
		return 0;
	else {
		var size = 0;
		
		for(var key in this.parameters)
			size++;
		
		return size;
	}
};

/**
 * AlopexConfig.xml 에 startPage에 정의된 시작페이지로 이동합니다
 * @function
 */
AlopexController.prototype.goStartPage = function goStartPage() {
	if(device.platformName == "Android" || window.isSimulator || device.platformName == "BlackBerry")
		alopexControllerD.goStartPage();
	else if(device.platformName == "iPhone" && !window.isSimulator)
		AlopexGap.exec("Alopex.goStartPage");
};

/**
 * 다른 페이지로 이동
 * @param action 이동할 페이지의 action 이름
 * @param params 이동시 전송할 데이터, 이동된 페이지에서 alopexController.parameters에서 조회 가능.
 */
AlopexController.prototype.navigate = function navigate(action, params) {
	if(device.platformName == "Android" || window.isSimulator || device.platformName == "BlackBerry") {
		var query = [];
		
		for(var name in params) {
			if(typeof(name) != "string")
				continue;
			
			query.push(name + "=" + escape(params[name]));
		}
		
		alopexControllerD.navigateWithQuery(action, query.join("&"));
	}
	else if(device.platformName == "iPhone" && !window.isSimulator)
		AlopexGap.exec("Alopex.navigate", action, params);
};

/**
 * Action 이름으로 페이지 이동
 * @param action 이동할 페이지의 action 이름
 *  
 */
AlopexController.prototype.navigateWithAction = function navigateWithAction(action) {
	if(device.platformName == "Android" || window.isSimulator || device.platformName == "BlackBerry")
		alopexControllerD.navigateWithAction(action);
	else if(device.platformName == "iPhone" && !window.isSimulator)
		AlopexGap.exec("Alopex.navigate", action);
};

/**
 * 새로운 페이지로 이동합니다.
 * @param action 이동할 페이지의 action 이름
 * @param params 이동할 페이지로 넘길 데이터
 * 
 */
AlopexController.prototype.navigateWithParameters = function navigateWithParameters(action, params) {
	if(device.platformName == "Android" || device.platformName == "BlackBerry" || window.isSimulator) {
		var query = [];
		
		for(var name in params) {
			if(typeof(name) != "string")
				continue;
			
			query.push(name + "=" + escape(params[name]));
		}
		
		alopexControllerD.navigateWithQuery(action, query.join("&"));
	}
	else if(device.platformName == "iPhone" && !window.isSimulator)
		AlopexGap.exec("Alopex.navigate", action, params);
	else if(window.isSimulator) {
		var query = [];
		
		for(var name in params) {
			if(typeof(name) != "string")
				continue;
				
			query.push(name + "=" + params[name]);
		}
		
		alopexControllerD.navigateWithQuery(action, query.join("&"));
	}
};

/**
 * 새로운 페이지로 이동합니다.
 * @param action 이동할 페이지의 action 이름 
 * @param query 전송할 URL query(key=sk_key&value=sk_value)
 */
AlopexController.prototype.navigateWithQuery = function navigateWithQuery(action, query) {
	if(device.platformName == "Android" || window.isSimulator || device.platformName == "BlackBerry")
		alopexControllerD.navigateWithQuery(action, query);
	else if(device.platformName == "iPhone" && !window.isSimulator) {	//TODO iphone navigateWithQuery => DONE
		var params = [];
		var paramsArray = query.split("&");
		
		for(var i = 0; i < paramsArray.length; i++) {
			var tmp = paramsArray[i].split("=");
			params[tmp[0]] = tmp[1];
		}
		
		AlopexGap.exec("Alopex.navigate", action, params);
	}
};

/**
 * 새로운 페이지로 이동합니다.
 * @param url 이동할 페이지의 url 상대경로(경로의 시작은 /uidef 아래)
 * @param params 이동할 페이지로 넘길 데이터
 */
AlopexController.prototype.navigateWithUrl = function navigateWithUrl(url, params) {
	if(device.platformName == "Android" || window.isSimulator || device.platformName == "BlackBerry") {
		var query = [];
		
		for(var name in params) {
			if(typeof(name) != "string")
				continue;
			
			query.push(name + "=" + escape(params[name]));
		}
		
		alopexControllerD.navigateWithUrl(url, query.join("&"));
	}
	else if(device.platformName == "iPhone" && !window.isSimulator) {
	}
};

/**
 * Back 버튼이 눌러졌을 시 실행되는 행동을 정의합니다.
 * 
 * @param method Back 버튼 클릭시 호출되는 함수
 */
AlopexController.prototype.setCustomizedBack = function setCustomizedBack(method) {
	var that = this;
	
	if(device.platformName == "Android" || window.isSimulator)
		setTimeout(function() { that.customizedBack = method; alopexControllerD.setCustomizedBack(method); }, 100);
	else if(device.platformName == "BlackBerry") {		
		this.customizedBack = method;
		alopexControllerD.setCustomizedBack(GetFunctionName(method));
	}
	else if(device.platformName == "iPhone" && !window.isSimulator)
		log.warn("iPhone does not support customized back");
};

AlopexController.prototype.setOnDestroy = function setOnDestroy(callback) {
	if(device.platformName == "Android")
		alopexControllerD.setOnDestroy(GetFunctionName(callback));
	else if(device.platformName == "BlackBerry") {
	}
	else if(device.platformName == "iPhone") {
	}
};

AlopexController.prototype.setOnPause = function setOnPause(callback) {
	if(device.platformName == "Android")
		alopexControllerD.setOnPause(GetFunctionName(callback));
	else if(device.platformName == "BlackBerry") {
	}
	else if(device.platformName == "iPhone") {
	}
};

/**
 * 반드시 모든 페이지에서 호출해야 되며, parameter setting 등 필수 로직이 실행됩니다. 
 * 
 * @param initHandler 로딩 후 호출되는 초기화 함수
 */
AlopexController.prototype.start = function start(initHandler) {
	if(device.platformName == "Android" || window.isSimulator || device.platformName == "BlackBerry") {
		if(device.platform != null)
			alopexControllerD.start(initHandler);
		else
			initHandler();
	}
	else if(device.platformName == "iPhone" && !window.isSimulator) {
		this.initHandler = initHandler;
		
		AlopexGap.exec("Preference.initPreferences");
		AlopexGap.exec("GlobalPreference.initPreferences");
		AlopexGap.exec("Alopex.initParameters", this.initHandler);
	}
};

/**
 * 
 * @param initHandler
 * 
 */
AlopexController.prototype.startWithWidget = function startWithWidget(initHandler) {
	if(device.platformName == "Android" || window.isSimulator || device.platformName == "BlackBerry") {
		if(device.platform != null)
			alopexControllerD.startWithWidget(initHandler);
		else
			initHandler();
	}
	else if(device.platformName == "iPhone" && !window.isSimulator) {
		this.initHandler = initHandler;
		
		AlopexGap.exec("Preference.initPreferences");
//		AlopexGap.exec("GlobalPreference.initPreferences");
		AlopexGap.exec("Alopex.initParametersWithWidget", this.initHandler);
	}
};

AlopexController.prototype.addExtraDelegator = function addExtraDelegator(className, interfaceName) {
	if(device.platformName == "Android" || window.isSimulator) {
		alopexControllerD.addExtraDelegator(className, interfaceName);
	} else if (device.platformName == "BlackBerry") {
		nativeExtensionD.addDelegator (className);
	}
};

AlopexController.prototype.executeNativeExtension = function executeNativeExtension(className, method, successCallback, errorCallback, options, arg0, arg1, arg2) {
	if(device.platformName == "Android" || window.isSimulator ) {
		alopexControllerD.executeNativeExtension(className, method, GetFunctionName(successCallback), GetFunctionName(errorCallback), options, arg0, arg1, arg2);
	} else if (device.platformName == "BlackBerry") {
		nativeExtensionD.executeNativeExtension(className, GetFunctionName(successCallback), GetFunctionName(errorCallback), options, arg0, arg1, arg2);
	} else if(device.platformName == "iPhone" && !window.isSimulator) {
		AlopexGap.exec("Alopex.executeNativeExtension", className, method, GetFunctionName(successCallback), GetFunctionName(errorCallback), options, arg0, arg1, arg2);
	}
};

var alopexController;

AlopexGap.addConstructor(function() {
	if(typeof alopexController == "undefined")
		alopexController = new AlopexController();
});
//AlopexController Class End


/**
 * NativeUI Class Start
 * 각 플랫폼의 네이티브 UI와 연동하는 클래스
 * @constructor
 */
function NativeUI() {
	/**
	 * ShowContextMenu에서 사용되는 메뉴명과 콜백함수의 목록
	 * @members
	 */
	this.contextCallbackFunctions = new Array;
	/**
	 * showSelectBox에서 오픈되는 셀렉트박스의 아이템들
	 * @members
	 */
	this.selectBoxItems = new Array;
	/**
	 * showMultiSelect에서 오픈되는 항목명과 선택여부의 목록
	 * @members
	 */
	this.multiSelectItems = new Array;
}

/**
 * 실행된 Progress Bar를 닫습니다. 
 * 
 */
NativeUI.prototype.dismissProgressDialog = function() {
	if(device.platformName == "Android" || device.platformName == "BlackBerry" || window.isSimulator)
		nativeUID.dismissProgressDialog();
	else if(device.platformName == "iPhone" && !window.isSimulator)
		AlopexGap.exec("NativeUI.dismissProgressDialog");
	else if(window.isSimulator)
		alopexControllerD.dismissProgressDialog();
};
/**
 * Progress Bar를 보여줍니다.
 * 
 */
NativeUI.prototype.showProgressDialog = function(message) {
	if(message == "" || message == undefined || message == null || message == "undefined" || message == "null")
		message = "Retrieving Data...";
	
	if(device.platformName == "Android" || window.isSimulator)
		nativeUID.showProgressDialog(message);
	else if (device.platformName == "BlackBerry") {
		if (message == undefined)
			nativeUID.showProgressDialog();
		else
			nativeUID.showProgressDialog(message);
	} else if(device.platformName == "iPhone" && !window.isSimulator)
		AlopexGap.exec("NativeUI.showProgressDialog");
	else if(window.isSimulator)
		alopexControllerD.showProgressDialog();
};


/**
 * 날짜 선택창 감춥니다.
 * @function
 */
NativeUI.prototype.cancelDatePicker = function() {
	if(device.platformName == "Android" || device.platformName == "BlackBerry" || window.isSimulator)
		nativeUID.cancelDatePicker();
	else if(device.platformName == "iPhone" && !window.isSimulator) {}
};
/**
 * 날짜 선택창 보여 줍니다.
 * @param callback 날짜를 선택한 후에 호출될 콜백함수. 콜백함수의 인자는 (year, month, day) 형식입니다.
 * 
 */
NativeUI.prototype.showDatePicker = function(callback) {
	if(device.platformName == "Android" || device.platformName == "BlackBerry" || window.isSimulator)
		nativeUID.showDatePicker(GetFunctionName(callback));
	else if(device.platformName == "iPhone" && !window.isSimulator)
		AlopexGap.exec("NativeUI.showDatePicker", GetFunctionName(callback));
};
/**
 * 기본날짜로 날짜 선택창 보이기
 * 
 * @param callback 날짜를 선택한 후에 호출될 콜백함수
 * @param year 기본 표시될 년도
 * @param month 기본 표시될 월
 * @param day 기본 표시될 일
 * 
 */
NativeUI.prototype.showDatePickerWithDefault = function(callback, year, month, day) {
	if(year < 1900) {
		log.warn("Set year to 1900 since " + year + " is not valid year.");
		year = 1900;
	}
	else if(year > 2100) {
		log.warn("Set year to 2100 since " + year + " is not valid year.");
		year = 2100;
	}
	
	if(month < 1) {
		log.warn("Set month to 1 since " + month + " is not valid month.");
		month = 1;
	}
	else if(month > 12) {
		log.warn("Set month to 12 since " + month + " is not valid month.");
		month = 12;
	}
	
	if(day < 1) {
		log.warn("Set day to 1 since " + day + " is not valid day.");
		day = 1;
	}
	else {
		if(month == 2) {
			if(year % 4 != 0) {
				if(day > 28) {
					log.warn("Set day to 28 since " + day + " is not valid day.");
					day = 28;
				}
			}
			else {
				if(day > 29) {
					log.warn("Set day to 29 since " + day + " is not valid day.");
					day = 29;
				}
			}
		}
		else if(month == 4 || month == 6 || month == 9 || month == 11) {
			if(day > 30) {
				log.warn("Set day to 30 since " + day + " is not valid day.");
				day = 30;
			}
		}
		else {
			if(day > 31) {
				log.warn("Set day to 31 since " + day + " is not valid day.");
				day = 31;
			}
		}
	}
	
	if(device.platformName == "Android" || window.isSimulator)
		nativeUID.showDatePickerWithDefault(GetFunctionName(callback), year, month - 1, day);
	else if(device.platformName == "iPhone" && !window.isSimulator)
		AlopexGap.exec("NativeUI.showDatePickerWithDefault", GetFunctionName(callback), year, month, day);
	else if (device.platformName == "BlackBerry")
		nativeUID.showDatePickerWithDefault(GetFunctionName(callback), year, month, day);
};

//callback에  ("AM" or "PM", "시간(1~12)", "분")로 호출해 주도록 함 
/**
 * 시간 선택창을 감춥니다.
 */
NativeUI.prototype.cancelTimePicker = function() {
	if(device.platformName == "Android" || device.platformName == "BlackBerry" || window.isSimulator)
		nativeUID.cancelTimePicker();
	else if(device.platformName == "iPhone" && !window.isSimulator) {}
};
/**
 * 시간 선택창 보여줍니다.
 * @param callback 시간을 선택한 후에 호출될 콜백함수. 콜백함수의 인자는 ("AM" or "PM", "시간(1~12)", "분") 형식입니다. 
 * 
 */
NativeUI.prototype.showTimePicker = function(callback) {
	if(device.platformName == "Android" || device.platformName == "BlackBerry" || window.isSimulator)
		nativeUID.showTimePicker(GetFunctionName(callback));
	else if(device.platformName == "iPhone" && !window.isSimulator)
		AlopexGap.exec("NativeUI.showTimePicker", GetFunctionName(callback));
};
/**
 * 인자로 주어진 시간으로 시간 선택창 보여집니다. callback에  ("AM" or "PM", "시간(1~12)", "분")로 호출해 주도록 함
 * 
 * @param callback 시간 선택한 후에 호출될 콜백함수
 * @param ampm: 오전 오후 구분자, “AM”or “PM”
 * @param hour: 시간, 1~12
 * @param min
 */
NativeUI.prototype.showTimePickerWithDefault = function(callback, ampm, hour, min) {
	if(ampm != "AM" && ampm != "am" && ampm != "PM" && ampm != "pm") {
		log.error("Insert AM, am, PM, or pm.");
		
		return;
	}
	
	if(hour < 1) {
		log.warn("Set hour to 1 since " + hour + " is not valid hour.");
		hour = 1;
	}
	else if(hour > 12) {
		log.warn("Set hour to 11 since " + hour + " is not valid hour.");
		hour = 12;
	}
	
	if(min < 0) {
		log.warn("Set min to 0 since " + min + " is not valid min.");
		min = 0;
	}
	else if(min > 59) {
		log.warn("Set min to 59 since " + min + " is not valid min.");
		min = 59;
	}
	
	if(device.platformName == "Android" || device.platformName == "BlackBerry" || window.isSimulator)
		nativeUID.showTimePickerWithDefault(GetFunctionName(callback), ampm, hour, min);
	else if(device.platformName == "iPhone" && !window.isSimulator)
		AlopexGap.exec("NativeUI.showTimePickerWithDefault", GetFunctionName(callback), ampm, hour, min);
};

/**
 * Context Menu Interface는 개선
 *   openContextMenu, getContextParameter를 showContextMenu, setContextMenuItem로 변경
 *   메뉴생성에 xml 대신 setContextMenu에서 메뉴명과 callback set한다.
 * 
 *   사용예)
 *   nativeUI.setContextMenuItem("삭제", onDeleteContextMenu);
 *   nativeUI.setContextMenuItem("수정", onDeleteContextMenu);
 *   nativeUI.setContextMenuItem("추가", onDeleteContextMenu);
 *   nativeUI.setContextMenuItem("취소", onDeleteContextMenu);
 *   nativeUI.showContextMenu();
*/

/**
 * 현재 열린 context menu를 닫습니다.
 * @function
 */
NativeUI.prototype.cancelContextMenu = function() {
	if(device.platformName == "Android" || device.platformName == "BlackBerry" || window.isSimulator)
		nativeUID.cancelContextMenu();
	else if(device.platformName == "iPhone" && !window.isSimulator) {}
};
/**
 * 컨텍스트 메뉴 아이템 설정.
 * 컨텍스트메뉴 show 전에 각각의 Menu Item 설정
 * name 메뉴표시명, callback 메뉴가 클릭되었을때 호출되는 callback function
 * @param name 컨텍스트 메뉴 아이템 명
 * @param callback 해당 컨텍스트 메뉴 아이템이 클릭 되었을 때 불려질 콜백함수
 * 
 */
NativeUI.prototype.setContextMenuItem = function(name, callback) {
	if(device.platformName == "Android" || window.isSimulator) {
		this.contextCallbackFunctions[name] = callback;
		nativeUID.setContextMenuItem(name);
	} 
	else if(device.platformName == "BlackBerry")
		nativeUID.setContextMenuItem(name, GetFunctionName(callback));
	else if(device.platformName == "iPhone" && !window.isSimulator)
		this.contextCallbackFunctions[name] = GetFunctionName(callback);
};
/**
 * 컨택스트 메뉴 보이기
 * 사용예)
 *   nativeUI.setContextMenuItem("삭제", onDeleteContextMenu);
 *   nativeUI.setContextMenuItem("수정", onDeleteContextMenu);
 *   nativeUI.setContextMenuItem("추가", onDeleteContextMenu);
 *   nativeUI.setContextMenuItem("취소", onDeleteContextMenu);
 *   nativeUI.showContextMenu();
 * 
 * @param title 컨텍스트 메뉴 제목
 */
NativeUI.prototype.showContextMenu = function(title) {
	if(device.platformName == "Android" || device.platformName == "BlackBerry" || window.isSimulator)
		nativeUID.showContextMenu(title);
	else if(device.platformName == "iPhone" && !window.isSimulator)
		AlopexGap.exec("NativeUI.showContextMenu", title, this.contextCallbackFunctions);
};

/** 
 * Select Box Interface는 추가
 * 
 * 사용예)
 *  nativeUI.setSelectBoxItem("알림창");
 *  nativeUI.setSelectBoxItem("상태표시줄");
 *  nativeUI.setSelectBoxItem("알람설정안함");
 *  nativeUI.showSelectBox(1);
*/
/**
 * 현재 열린 select box를 닫습니다.
 */
NativeUI.prototype.cancelSelectBox = function() {
	if(device.platformName == "Android" || device.platformName == "BlackBerry" || window.isSimulator)
		nativeUID.cancelSelectBox();
	else if(device.platformName == "iPhone" && !window.isSimulator) {}
};
/**
 * select box의  아이템 설정합니다.
 * SelectBox show 전에 각각의 Item 설정해야 합니다.
 * 
 * @param name 표시될 아이템 명
 */
NativeUI.prototype.setSelectBoxItem = function(name) {
	if(device.platformName == "Android" || window.isSimulator) {
		this.selectBoxItems.push(name);
		nativeUID.setSelectBoxItem(name);
	} else if (device.platformName == "BlackBerry") {
		this.selectBoxItems.push(name);
		if (typeof name == 'boolean') {
			if (name) 
				nativeUID.setSelectBoxItem("true");
			else
				nativeUID.setSelectBoxItem("false");
		} else {
			nativeUID.setSelectBoxItem(name);
		}
	}
	else if(device.platformName == "iPhone" && !window.isSimulator)
		this.selectBoxItems.push(name);
};
/**
 * select box를 화면에 보여줍니다.
 * @param callback 선택된 후 불려질 콜백함수. 콜백함수의 인자로 선택된 아이템의 인덱스 값이 전달됩니다.
 * @param defaultSelectedIndex 기본 선택되어 있는 아이템 idx
 * 
 */
NativeUI.prototype.showSelectBox = function(callback, defaultSelectedIndex) {
	if(device.platformName == "Android" || device.platformName == "BlackBerry" || window.isSimulator)
		nativeUID.showSelectBox(GetFunctionName(callback), defaultSelectedIndex);
	else if(device.platformName == "iPhone" && !window.isSimulator)
		AlopexGap.exec("NativeUI.showSelectBox", GetFunctionName(callback), defaultSelectedIndex, this.selectBoxItems);
};

/** 
 * Multi Select Interface는 추가
 * 
 * 사용예)
 *  nativeUI.setMultiSelectItem("알림창", true);
 *  nativeUI.setMultiSelectItem("상태표시줄", false);
 *  nativeUI.setMultiSelectItem("사운드", true);
 *  nativeUI.showMultiSelect();
*/
/**
 * 다중 선택창 감춥니다.
 */
NativeUI.prototype.cancelMultiSelect = function() {
	if(device.platformName == "Android" || device.platformName == "BlackBerry" || window.isSimulator)
		nativiUID.cancelMultiSelect();
	else if(device.platformName == "iPhone" && !window.isSimulator) {}
};
/**
 * 다중 선택창 아이템 설정합니다.
 * MultiSelect show 전에 각각의 Item 설정하고, selected는 check 여부 boolean형식으로 나타냅니다. 
 * 
 * @param name 표시될 아이템 명
 * @param selected 다중 선택창이 화면에 보여질 때 해당 아이템이 기본 체크될 지 여부
 */
NativeUI.prototype.setMultiSelectItem = function(name, selected) {
	if(device.platformName == "Android" || device.platformName == "BlackBerry" || window.isSimulator) {
		this.multiSelectItems[name] = selected;
		nativeUID.setMultiSelectItem(name, selected);
	}
	else if(device.platformName == "iPhone" && !window.isSimulator) {
		this.multiSelectItems[name] = selected;
		AlopexGap.exec("NativeUI.setMultiSelectItem", name);
	}
};
/**
 * 다중 선택창 보여줍니다.
 * @param callback 선택 후에 불려질 콜백함수
 * 
 */
NativeUI.prototype.showMultiSelect = function(callback) {
	if(device.platformName == "Android" || device.platformName == "BlackBerry" || window.isSimulator)
		nativeUID.showMultiSelect(GetFunctionName(callback));
	else if(device.platformName == "iPhone" && !window.isSimulator)
		AlopexGap.exec("NativeUI.showMultiSelect", GetFunctionName(callback), this.multiSelectItems);
};

var nativeUI;

AlopexGap.addConstructor(function() {
	if(typeof nativeUI == "undefined")
		nativeUI = new NativeUI();
});
// NativeUI Class End

//HandShaking 기능은 Sensor로 이동
//센서 관련 기능은 여기로 통합 
//Comment Block -> 향후 보완 적용 

//function Sensor() {
//this.handShake = null;
//}
//
//Sensor.prototype.handShaking = function() {
//	if(device.platformName == "Android" || window.isSimulator ) {
//		if(this.handShake != null)
//			this.openContextMenu(this.handShake);
//	}
//	else if(device.platformName == "iPhone" && !window.isSimulator) {}
//}
//
////추후 추가 
//Sensor.prototype.turnOffSensor = function() {
//	if(device.platformName == "Android" || window.isSimulator ) {
//		alopexControllerD.turnOffSensor();
//	} else if(device.platformName == "iPhone" && !window.isSimulator) {
//	}
//}
//
//Sensor.prototype.turnOnSensor = function() {
//	if(device.platformName == "Android" || window.isSimulator ) {
//		alopexControllerD.turnOnSensor();
//	} else if(device.platformName == "iPhone" && !window.isSimulator) {
//	}
//}
//
//var sensor;
//
//AlopexGap.addConstructor(function() {
//	if(typeof sensor == "undefined") {
//		sensor = new Sensor();
//	}
//});

/**
 ****************************************** Application Class ***********************************************
 */


/**
 * 다른 어플을 실행하기 위한 클래스
 * @constructor
 */
function Application() {
	/**
	 * 다른 프로그램을 호출한 후 종료 되었을 때 불려질 콜백함수 
	 * @members
	 */
	this.callback = null;
	/**
	 * 다른 프로그램을 실행할 때 같이 넘겨줄 값 목록
	 * @members
	 */
	this.data = [];
	this.resultData = [];
}

/**
 * 다른 프로그램 실행 시 넘겨줄 값을 초기화
 * 
 */
Application.prototype.clear = function() {
	if(device.platformName == "Android" || window.isSimulator)
		this.data = [];
	else if (device.platformName == "BlackBerry") {
		this.data = [];
		applicationD.clear();
	}
	else if(device.platformName == "iPhone" && !window.isSimulator) {}
};

/**
 * 다른 프로그램 실행 시 넘겨줄 parameter 값 가져오기
 * @param key 가져올 값의 키
 * 
 */
Application.prototype.get = function(key){
	if(device.platformName == "Android" || window.isSimulator) {
		var returnValue = this.data[key];
		
		if(typeof returnValue != "undefined") {
			if(returnValue.indexOf("&") != -1)
				return returnValue.split("&");
			else 
				return [returnValue];
		}
		else
			return null;
	}
	else if (device.platformName == "BlackBerry") {
		var returnValue = applicationD.get(key);
		
		if(typeof returnValue != "undefined") {
			if(returnValue.indexOf("&") != -1)
				return returnValue.split("&");
			else 
				return [returnValue];
		}
		else
			return null;
		
	}
	else if(device.platformName == "iPhone" && !window.isSimulator) {}
};

/**
 * 다른 프로그램 실행 시 넘겨줄 parameter의 size
 * 
 */
Application.prototype.getSize = function() {
	if(device.platformName == "Android" || device.platformName == "BlackBerry" || window.isSimulator) {
		var size = 0;
		
		for(var key in this.data)
			size++;
		
		return size;
	} else if(device.platformName == "iPhone" && !window.isSimulator) {}
};

/**
 * 다른 프로그램 실행 시 넘겨줄 parameter를 boolean 형식으로 추가
 * @param key 넘겨줄 키
 * @param value 넘겨줄 값
 * 
 */
Application.prototype.setBoolean = function(key, value) {
	if(device.platformName == "Android" || device.platformName == "BlackBerry" )
		applicationD.setBoolean(key, value);
	else if(device.platformName == "iPhone" && !window.isSimulator) {}
};

/**
 * 다른 프로그램 실행 시 넘겨줄 parameter를 float 형식으로 추가
 * @param key 넘겨줄 키
 * @param value 넘겨줄 값
 * 
 */
Application.prototype.setFloat = function(key, value) {
	if(device.platformName == "Android" || device.platformName == "BlackBerry" || window.isSimulator)
		applicationD.setFloat(key, value);
	else if(device.platformName == "iPhone" && !window.isSimulator) {}
};

/**
 * 다른 프로그램 실행 시 넘겨줄 parameter를 int 형식으로 추가
 * @param key 넘겨줄 키
 * @param value 넘겨줄 값
 * 
 */
Application.prototype.setInt = function(key, value) {
	if(device.platformName == "Android" || device.platformName == "BlackBerry" || window.isSimulator)
		applicationD.setInt(key, value);
	else if(device.platformName == "iPhone" && !window.isSimulator) {}
};

/**
 * 다른 프로그램 실행 시 넘겨줄 parameter를 String 형식으로 추가
 * @param key 넘겨줄 키
 * @param value 넘겨줄 값
 * 
 */
Application.prototype.setString = function(key, value) {
	if(device.platformName == "Android" || device.platformName == "BlackBerry" || window.isSimulator)
		applicationD.setString(key, value + "");
	else if(device.platformName == "iPhone" && !window.isSimulator) {}
};

/**
 * 다른 Alopex 앱을 실행 시킵니다.
 * @param identifier Alopex 앱의 식별자
 * @param actionName Alopex 앱의 한 페이지 지정
 * @param parameters 페이지에 전달할 데이터. Map의 Array 타입.
 */
Application.prototype.startAlopexApplication = function(identifier, actionName, parameters) {
	if(device.platformName == "Android" || window.isSimulator) {
		for(var name in parameters)
			applicationD.setString(name, parameters[name]);
		
		applicationD.startAlopexApplication(identifier, actionName);
	}
	else if(device.platformName == "BlackBerry") {
		for(var name in parameters)
			applicationD.setString(name, parameters[name]);
		
		applicationD.startAlopexApplication(identifier, actionName);
	}
	else if(device.platformName == "iPhone" && !window.isSimulator)
		AlopexGap.exec("Application.startAlopexApplication", identifier, actionName, parameters);
};
/**
 * 다른 Alopex 앱을 실행시킵니다. 실행된 앱은 exitWithResult로 결과값을 caller 앱에 리턴합니다.
 * @param identifier
 * @param actionName
 * @param parameters
 * @param callback 실행된 앱이 종료될 시 실행되는 콜백함수
 */
Application.prototype.startAlopexApplicationWithResult = function(identifier, actionName, parameters, callback) {
	if(device.platformName == "Android" || window.isSimulator) {
		for(var name in parameters)
			applicationD.setString(name, parameters[name]);
		
		applicationD.startAlopexApplicationWithResult(identifier, actionName, GetFunctionName(callback));
	}
	else if(device.platformName == "BlackBerry") {
		for(var name in parameters)
			applicationD.setString(name, parameters[name]);
		applicationD.startAlopexApplicationWithResult(identifier, actionName, GetFunctionName(callback));
	}
	else if(device.platformName == "iPhone" && !window.isSimulator)
		AlopexGap.exec("Application.startAlopexApplicationWithResult", identifier, actionName, parameters, GetFunctionName(callback));
};

/**
 * 각 해당 플랫폼의 다른 앱을 실행합니다.
 * - applicationName: 어플리케이션명
 * @param identifier 실행할 어플리케이션의 id. ex) android는 package명, iPhone는 scheme
 * @param callback 다른 프로그램이 종료 되었을 때 호출될 콜백함수
 * 
 */
Application.prototype.startApplication = function(identifier, callback) {
	if(device.platformName == "Android" )
		;//applicationD.startApplication(identifier);
	else if(device.platformName == "BlackBerry") {
		this.callback = callback;
		applicationD.startApplication(applicationName, callback);
		//BlackBerry:
		//Application Name: Name Below Icon
		//Identifier = Package Name = (Device Menu) Setup -> Applications -> Package Name
	}
	else if(device.platformName == "iPhone" && !window.isSimulator)
		AlopexGap.exec("Application.startApplication", identifier, callback);
};

/**
 * 다른 앱을 실행합니다.
 * @param identifier
 * @param callback
 */
Application.prototype.startApplicationWithResult = function(identifier, callback) {
	if(device.platformName == "Android" || window.isSimulator ) {
//		this.callback = callback;
//		
//		applicationD.startApplication(identifier);
	}
	else if(device.platformName == "BlackBerry") {
	}
	else if(device.platformName == "iPhone" && !window.isSimulator)
		AlopexGap.exec("Application.startApplicationWithResult", identifier, callback);
};

var application;

AlopexGap.addConstructor(function() {
	if(typeof application == "undefined")
		application = new Application();
});

/**
 * 주소록 연동을 위한 클래스
 * @constructor
 */
function Contact() {
	//Use those below variables for reference.
	this.CONTACT_ID = "contactId";
	this.FIRST_NAME = "firstName";
	this.LAST_NAME = "lastName";
	this.MOBILE_PHONE = "mobilePhone";
	this.WORK_PHONE = "workPhone";
	this.EMAIL = "email";
	this.ORGANIZATION = "organization";
	this.DEPARTMENT = "department";
	this.JOB_TITLE = "jobTitle";
	/**
	 * 가져온 주소록 항목을 가지고 있는 목록
	 * @members
	 */
	this.contacts = [];
	/**
	 * 가져온 주소록 항목의 개수
	 * @members
	 */
	this.length = 0;
}

//contact Param에 key-value pair로 주소록 값 저장
//KEY: firstName, lastName, mobilePhone, workPhone, email, organization(회사명), department(부서), jobTitle(직위) 
/**
 * 새로운 주소록을  저장합니다.
 * @param contactParam 주소록 항목들
 * 			firstName, lastName, mobilePhone, workPhone, email, organization(회사명), department(부서), jobTitle(직위)
 * @param successCallback 주소록을 가져온 후 호출될 콜백함수
 * 
 */ 
Contact.prototype.addContact = function(contactParam, successCallback) {
	if(device.platformName == "Android" || device.platformName == "BlackBerry" || window.isSimulator )
		contactD.addContact(contactParam["firstName"], contactParam["lastName"], contactParam["mobilePhone"], contactParam["workPhone"], contactParam["email"], contactParam["organization"], contactParam["department"], contactParam["jobTitle"], GetFunctionName(successCallback));
	else if(device.platformName == "iPhone" && !window.isSimulator)
		AlopexGap.exec("Contact.addContact", contactParam, GetFunctionName(successCallback), GetFunctionName(errorCallback));
};

/**
 * 기존에 존재하는 주소록을 삭제합니다.
 * @param contactId 특정 contact 아이디
 * @param successCallback 삭제 성공시 호출되는 콜백함수
 * @param errorCallback 삭제 실패시 호출되는 콜백함수
 */
Contact.prototype.deleteContact = function(contactId, successCallback, errorCallback) {
	if(contactId != null && contactId != undefined && contactId != "null" && contactId != "undefined" && contactId != "") {
		if(device.platformName == "Android"  || window.isSimulator) {
			if(!isNaN(contactId))
				contactD.deleteContact(contactId, GetFunctionName(successCallback), GetFunctionName(errorCallback));
			else
				errorCallback(contactId + " is not a correct contactId");
		}
		else if(device.platformName == "BlackBerry") {
			contactD.remove(contactId, GetFunctionName(successCallback), GetFunctionName(errorCallback));
		}
		else if(device.platformName == "iPhone" && !window.isSimulator) {
			AlopexGap.exec("Contact.deleteContact", contactId, GetFunctionName(successCallback), GetFunctionName(errorCallback));
		}
	}
	else
		errorCallback(contactId + " is not a correct contactId");
};

/**
 * 인자로 주어진 contact id를 이용해 contact정보를 받아옵니다.
 * @param contactId 특정 contact 아이디
 * @param successCallback 성공시 호출되는 콜백함수
 * @param errorCallback 실패시 호출되는 콜백함수
 */
Contact.prototype.getContact = function(contactId, successCallback, errorCallback) {
	if(device.platformName == "Android" || window.isSimulator)
		contactD.getContact(contactId, GetFunctionName(successCallback), GetFunctionName(errorCallback));
	else if(device.platformName == "BlackBerry") {
		contactD.getContact(contactId, GetFunctionName(successCallback), GetFunctionName(errorCallback));
	}
	else if(device.platformName == "iPhone" && !window.isSimulator) {
		AlopexGap.exec("Contact.getContact", contactId, GetFunctionName(successCallback), GetFunctionName(errorCallback));
	}
};

//TODO 향후 전체 항목 조회 추가? 또는 filter 기능추가 (Release v1.0 에서는 그대로)
/**
 * 주소록 중 이메일이 있는 contact만 리턴합니다.
 * @param successCallback 주소록을 가져온 후 호출될 콜백함수
 */
Contact.prototype.getContactsOnlyEmail = function(successCallback) {
	if(device.platformName == "Android" || device.platformName == "BlackBerry" || window.isSimulator)
		contactD.getContactsOnlyEmail(GetFunctionName(successCallback));
	else if(device.platformName == "iPhone" && !window.isSimulator)
		AlopexGap.exec("Contact.getContactsOnlyEmail", GetFunctionName(successCallback));
};

/**
 * filter에 선택된 검색조건을 가지고 contact를 검색합니다.
 * @param successCallback
 * @param errorCallback
 * @param filter 검색조건. 
 * 		filter['contactId'] 
 * 		filter['firstName'] 이름
 * 		filter['lastName'] 성
 * 		filter['email'] 이메일
 * 		filter['mobilePhone']
 * @param options 검색옵션.
 * 		options['and'] true이면 and로 filter 결합, false이면 or로 결합. 기본은 and
 * @return
 */
Contact.prototype.searchContact = function(filter, options, successCallback, errorCallback) {
	if(device.platformName == "Android" || window.isSimulator) {
		var query = [];
		
		for(var name in filter) {
			if(filter[name] != "" && filter[name] != "null" && filter[name] != null && filter[name] != undefined && filter[name] != "undefined")
				query.push(name + "=" + encodeURI(filter[name]));
		}
		
		contactD.searchContact(query.join("&"), options, GetFunctionName(successCallback), GetFunctionName(errorCallback));
	}
	else if(device.platformName == "BlackBerry") {
		var query = [];
		var opt;
		
		for(var name in filter) {
			if(filter[name] != "" && filter[name] != "null" && filter[name] != null && filter[name] != undefined && filter[name] != "undefined")
				query.push(name + "=" + encodeURI(filter[name]));
		}
		
		if (typeof options == "string"){
			if (options == "true")
				opt = true;
			else
				opt = false;
		} else
			opt = options;
			
		contactD.searchContact(query.join("&"), opt, GetFunctionName(successCallback), GetFunctionName(errorCallback));
		
	}
	else if(device.platformName == "iPhone" && !window.isSimulator) {
		AlopexGap.exec("Contact.searchContact", filter, options, GetFunctionName(successCallback), GetFunctionName(errorCallback));
	}
};

/**
 * 주어진 contact id의 주소록을 수정합니다.
 * @param contactId 특정 contact 아이디
 * @param contactParam 변경될 주소록 정보
 * @param successCallback 성공시 호출되는 콜백함수
 * @param errorCallback 실패시 호출되는 콜백함수
 */
Contact.prototype.updateContact = function(contactId, contactParam, successCallback, errorCallback) {
	if(device.platformName == "Android" || window.isSimulator ) {
		var query = [];
		
		for(var name in contactParam) {
			if(contactParam[name] != "" && contactParam[name] != "null" && contactParam[name] != null && contactParam[name] != undefined && contactParam[name] != "undefined")
				query.push(name + "=" + encodeURI(contactParam[name]));
		}
		
		if(!isNaN(contactId))
			contactD.updateContact(contactId, query.join("&"), GetFunctionName(successCallback), GetFunctionName(errorCallback));
		else
			errorCallback(contactId + " is not a correct contactId");
	}
	else if(device.platformName == "BlackBerry") {
		var query = [];
		
		for(var name in contactParam) {
			if(contactParam[name] != "" && contactParam[name] != "null" && contactParam[name] != null && contactParam[name] != undefined && contactParam[name] != "undefined")
				query.push(name + "=" + encodeURI(contactParam[name]));
		}
		
		contactD.updateContact(contactId, query.join("&"), GetFunctionName(successCallback), GetFunctionName(errorCallback));
	}
	else if(device.platformName == "iPhone" && !window.isSimulator) {
		AlopexGap.exec("Contact.updateContact", contactId, contactParam, GetFunctionName(successCallback), GetFunctionName(errorCallback));
	}
};

var contact;

AlopexGap.addConstructor(function() {
	if(typeof contact == "undefined")
		contact = new Contact();
});



//File 전체 Comment Block 후 보완 적용 
//function File() {
//	if(device.platformName == "Android" || window.isSimulator ) {
//		var callback = null;
//	} else if(device.platformName == "iPhone" && !window.isSimulator) {
//	}
//
//}
//
//File.prototype.isExist = function(fileName) {
//	if(device.platformName == "Android" || window.isSimulator ) {
//		return fileD.isExist(fileName);
//	} else if(device.platformName == "iPhone" && !window.isSimulator) {
//		AlopexCommand.exec("File.isExists",fileName);
//	}
//}
//
//File.prototype.isDirectory = function(fileName) {
//	if(device.platformName == "Android" || window.isSimulator ) {
//		return fileD.isDirectory(fileName);
//	} else if(device.platformName == "iPhone" && !window.isSimulator) {
//		AlopexCommand.exec("File.isDirectory",fileName);
//	}
//}
//
//File.prototype.mkDir = function(fileName) {
//	if(device.platformName == "Android" || window.isSimulator ) {
//		return fileD.mkDir(fileName);
//	} else if(device.platformName == "iPhone" && !window.isSimulator) {
//		AlopexCommand.exec("File.mkDir",fileName);
//	}
//
//}
//
//File.prototype.deleteDirectory = function(srcLocation) {
//	if(device.platformName == "Android" || window.isSimulator ) {
//		return fileD.deleteDirectory(srcLocation);
//	} else if(device.platformName == "iPhone" && !window.isSimulator) {
//		AlopexCommand.exec("File.deleteDirectory",fileName);
//	}
//
//}
//
//File.prototype.createFile = function(fileName) {
//	if(device.platformName == "Android" || window.isSimulator ) {
//		return fileD.createFile(fileName);
//	} else if(device.platformName == "iPhone" && !window.isSimulator) {
//		AlopexCommand.exec("File.createFile",fileName);
//	}
//}
//
//File.prototype.copyFile = function(srcFileLocation, tgtFileLocation) {
//	if(device.platformName == "Android" || window.isSimulator ) {
//		return fileD.copyFile(srcFileLocation, tgtFileLocation);
//	} else if(device.platformName == "iPhone" && !window.isSimulator) {
//		AlopexCommand.exec("File.copyFile",srcFileLocation, tgtFileLocation);
//	}
//}
//
//File.prototype.moveFile =function(srcFileLocation, tgtFileLocation) {
//	if(device.platformName == "Android" || window.isSimulator ) {
//		return fileD.moveFile(srcFileLocation, tgtFileLocation);
//	} else if(device.platformName == "iPhone" && !window.isSimulator) {
//		AlopexCommand.exec("File.moveFile",srcFileLocation, tgtFileLocation);
//	}
//}
//
//File.prototype.deleteFile = function(fileName) {
//	if(device.platformName == "Android" || window.isSimulator ) {
//		return fileD.deleteFile(fileName);
//	} else if(device.platformName == "iPhone" && !window.isSimulator) {
//		AlopexCommand.exec("File.deleteFile",fileName);
//	}
//}
//
//
//File.prototype.renameFile= function(srcFileLocation, tgtFileLocation) {
//	if(device.platformName == "Android" || window.isSimulator ) {
//		return fileD.renameFile(srcFileLocation, tgtFileLocation);
//	} else if(device.platformName == "iPhone" && !window.isSimulator) {
//		AlopexCommand.exec("File.renameFile",srcFileLocation, tgtFileLocation);
//	}
//}
//
//File.prototype.read = function(fileName) {
//	if(device.platformName == "Android" || window.isSimulator ) {
//		return fileD.read(fileName);
//	} else if(device.platformName == "iPhone" && !window.isSimulator) {
//		return AlopexCommand.exec("File.read",fileName);
//	}
//}
//
//File.prototype.write = function(fileLocation, content) {
//	if(device.platformName == "Android" || window.isSimulator ) {
//		return fileD.write(fileLocation, content);
//	} else if(device.platformName == "iPhone" && !window.isSimulator) {
//		AlopexCommand.exec("File.file",fileLocation, content, "false");
//	}
//}
//
//File.prototype.unzip = function(sourceLocation, callback) {
//	if(device.platformName == "Android" || window.isSimulator ) {
//		this.callback = callback;
//		
//		fileD.unzip(sourceLocation);
//	} else if(device.platformName == "iPhone" && !window.isSimulator) {
//	}
//}
//
//var file;
//AlopexGap.addConstructor(function() {
//	if(typeof file == "undefined") {
//		file = new File();
//	}
//});







/**
 * Http 호출을 위한 클래스, Alopex 에서는 성능을 위해 http 호출은 네이티브에서 처리를 한 후에 결과값을 다시 javascript로 넘겨준다.
 * @constructor
 */
function Http(){
	/**
	 * http로 읽어온 값을 가지고 있는 변수
	 * @members
	 */
	this.response = null;
	/**
	 * 오류가 난 경우 메시지
	 * @members
	 */
	this.error = null;
	/**
	 * http를 요청을 하고 결과값을 받을 콜백함수
	 * @members
	 */
	this.successCallback = null;
	/**
	 * http오류가 난 경우 호출될 콜백함수
	 * @members
	 */
	this.errorCallback = null;
	/**
	 * 테스트용으로 이용하는 ajaxRequest 내부 변수
	 * @members
	 */
	this.ajaxRequest = null;	
	
	if(device.platformName == "iPhone")
		this.headers = [];
}

Http.prototype.getHeader = function getHeader(key) {
	if(device.platformName == "Android" || window.isSimulator)
		return httpD.getHeader(key);
	else if(device.platformName == "BlackBerry") {
		return httpD.getHeader(key);
	}
	else if(device.platformName == "iPhone") {
        return this.headers[key];
	}
};

/**
 * http 요청 함수
 * TODO 이 Method는 request의 GET, POST를 Key Value Parameters로보내기 (xml body 안됨) => iPhone DONE
 * 
 * @param url 호출할 url
 * @param method “GET” or “POST”
 * @param params 전송할 데이터 parameter
 * @param successCallback http 요청 수 결과값을 받을 콜백함수
 * @param errorCallback http 오류 시 호출될 콜백함수
 */
Http.prototype.request = function(url, method, params, successCallback, errorCallback) {
	if(device.platformName == "Android" || window.isSimulator ) {		//Android/BlackBerry GET/POST 구현, params는 array
		var query = "";
		
		for(var name in params)
			query += (name + "=" + params[name] + "&");
		
		query = query.substring(0, query.length - 1);
		
		this.successCallback = successCallback;
		this.errorCallback = errorCallback;
		
		httpD.request(url, method, query);
	}
	else if(device.platformName == "BlackBerry") {
		if(httpD.isAuth()) {
			var cookie = globalPreference.getString("cookie", "");
			
			if(cookie == "")
				alopexController.navigate(httpD.getLoginAction(), null);
			else {
				cookie = cookie.substr(0, cookie.lastIndexOf(";"));
				http.setHeader("Cookie", cookie);
			}
		}
		
		var query = "";
		
		for(var name in params)
			query += (name + "=" + params[name] + "&");
		
		query = query.substring(0, query.length - 1);
		
		this.successCallback = function() {
			try {
				var xml = (new DOMParser()).parseFromString(this.response, "text/xml");
				var result = xml.getElementsByTagName("result")[0].firstChild.nodeValue;
				
				log.log("HTTP Result : " + result);
				
				if(result == "1100") {
					alopexController.navigate(httpD.getLoginAction(), null);
					nativeUI.dismissProgressDialog();
					
					return;
				}
			} catch(e) {
				successCallback();
			}
			
			successCallback();
		};
		
		this.errorCallback = errorCallback;

		http.setHeader("DEVICE", deviceD.deviceName);
		http.setHeader("OS", deviceD.platform);
		http.setHeader("OS_VERSION", deviceD.osVersion);
		http.setHeader("DEVICE_ID", deviceD.uuid);
		
		http.response = httpD.request(url, method, query);
		
		if(http.response != undefined)
			eval(GetFunctionName(successCallback)+"()");
		else
			eval(GetFunctionName(errorCallback)+"()");
	}
	else if(device.platformName == "iPhone" && !window.isSimulator)
		AlopexGap.exec("Http.request", GetFunctionName(successCallback), GetFunctionName(errorCallback), url, method, params);
	else
		this.requestAjax(url, method, params);
};

/**
 * HTTP Post 방식으로 데이터를 요청합니다.
 * TODO 이 Method는 body로 담아서 Post로보내는 Method
 * 
 * @param url 호출할 url
 * @param body 전송할 내용. XML 형식으로 지정해주어야 합니다. (XmlHandler의 make메소드 이용.)
 * @param successCallback 요청 성공시 결과값을 받을 콜백함수
 * @param errorCallback 요청 오류 시 호출될 콜백함수
 */ 
Http.prototype.requestPostBody = function(url, body, successCallback, errorCallback) {
	if(device.platformName == "Android" ) {
		this.successCallback = successCallback;
		this.errorCallback = errorCallback;
		
		httpD.requestPostBody(url, body);
	}
	else if(device.platformName == "BlackBerry") {
		if(httpD.isAuth()) {
			var cookie = globalPreference.getString("cookie", "");
			
			if(cookie == "") {
				alopexController.navigate(httpD.getLoginAction(), null);
				nativeUI.dismissProgressDialog();
				
				return;
			}
			else {
				cookie = cookie.substr(0, cookie.lastIndexOf(";"));
				http.setHeader("Cookie", cookie);
			}
		}
		
		this.successCallback = function() {
			try {
				var xml = (new DOMParser()).parseFromString(this.response, "text/xml");
				var result = xml.getElementsByTagName("result")[0].firstChild.nodeValue;
				
				log.log("HTTP Result : " + result);
				
				if(result == "1100") {
					alopexController.navigate(httpD.getLoginAction(), null);
					nativeUI.dismissProgressDialog();
					
					return;
				}
			} catch(e) {
				successCallback();
			}
			
			successCallback();
		};
		
		this.errorCallback = errorCallback;
		
		http.setHeader("DEVICE", deviceD.deviceName);
		http.setHeader("OS", deviceD.platform);
		http.setHeader("OS_VERSION", deviceD.osVersion);
		http.setHeader("DEVICE_ID", deviceD.uuid);
		
		http.response = httpD.requestPostBody(url, body);
		
		if(http.response != undefined)
			eval(GetFunctionName(successCallback)+"()");
		else
			eval(GetFunctionName(errorCallback)+"()");
	}
	else if(device.platformName == "iPhone" && !window.isSimulator){
		this.headers = [];
		window["successCallback"] = successCallback;
		window["errorCallback"] = errorCallback;

		AlopexGap.exec("Http.requestPostBody", "successCallback", "errorCallback", url, body);
	}
	else if(window.isSimulator) {
		this.successCallback = successCallback;
		this.errorCallback = errorCallback;
		
		httpD.request(url, "POST", body);
	}
	else
		this.requestAjax(url, method, params);
};

/**
 * 요청문의 Header를 설정합니다.
 * @param key 추가할 헤더의 키값
 * @param value 추가할 헤더의 데이터
 */
Http.prototype.setHeader = function(key, value) {
	if(device.platformName == "Android" || window.isSimulator)
		httpD.setHeader(key, value);
	else if(device.platformName == "BlackBerry")
		httpD.setHeader(key, value);
	else if(device.platformName == "iPhone" && !window.isSimulator)
		AlopexGap.exec("Http.setHeader", key, value);
};

Http.prototype.setTimeout = function setTimeout(timeout) {
	if(isNaN(timeout))
		return;
	
	if(device.platformName == "Android" || window.isSimulator)
		httpD.setTimeout(parseInt(timeout, 10));
	else if(device.platformName == "BlackBerry")
		;
	else if(device.platformName == "iPhone" && !window.isSimulator)
		;
};

Http.prototype.upload = function upload(filePath, uploadUrl, successCallback, errorCallback) {
	if(device.platformName == "Android" || window.isSimulator )
		httpD.upload(filePath, uploadUrl, GetFunctionName(successCallback), GetFunctionName(errorCallback));
	else if(device.platformName == "BlackBerry") {
		httpD.upload(filePath, uploadUrl, GetFunctionName(successCallback), GetFunctionName(errorCallback));
	}
	else if(device.platformName == "iPhone" && !window.isSimulator) {
	}
};

/**
 * 
 * @param url
 * @param method
 * @param params
 * 
 */
Http.prototype.requestAjax = function(url, method, params) {
	try {
		
	if(window.XMLHttpRequest) {
		try {
			this.ajaxRequest = new XMLHttpRequest();
		} catch(e) {
			this.ajaxRequest = false;
		}
	}
	else if(window.ActiveXObject) {
		try {
			this.ajaxRequest = new ActiveXObject("Msxml2.XMLHTTP");
		} catch(e) {
			try {
				this.ajaxRequest = new ActiveXObject("Microsoft.XMLHTTP");
			} catch(ex1) {
				this.ajaxRequest = false;
			}
		}
	}
	
	if(!this.ajaxRequest) {
		log.error("Http.requestAjax: ajax not avaliable");
		return;
	}
	 
	this.ajaxRequest.onreadystatechange = onHttpRequestAjax;

	if(method == "post" || method == "POST") {
		var urlStr = "http://localhost:8080/proxy.jsp?url=" + encodeURIComponent(url);
		this.ajaxRequest.open("POST", urlStr, true);
		
		var encodeParams = params;
		this.ajaxRequest.setRequestHeader("Content-length", encodeParams.length);
		this.ajaxRequest.setRequestHeader("Connection", "close");
		
		this.ajaxRequest.send(encodeParams);	
	} else {
		var urlStr = "http://localhost:8080/proxy.jsp?url=" + encodeURIComponent(url);
		this.ajaxRequest.open("GET", urlStr, true);
		this.ajaxRequest.send("");	
	}
	
	} catch(ex) {
		log.error(ex);
	}
};

function onHttpRequestAjax() {
	if(http.ajaxRequest.readyState == 4) {
		if(http.ajaxRequest.status == 200) {
			log.log("Http.onHttpRequestWithAjax: " + http.ajaxRequest.responseText );
			
			http.response = http.ajaxRequest.responseText;
			try {
				http.successCallback();
			} catch(e) {
				log.error(e);
			}
		}
		else {
			log.log("Http.onHttpRequestWithAjax: " + http.ajaxRequest.responseText );
			try {
			http.errorCallback();
			} catch(e) {
				log.error(e);
			}
		}
	}
}

var http;

AlopexGap.addConstructor(function() {
	if(typeof http == "undefined")
		http = new Http();
});






/**
 * 전화관련 기능을 연동하기 위한 클래스
 * @constructor
 */
function Phone() {
}

/**
 * 전화걸기 내장 프로그램 실행
 * @param number 전화할 전화번호
 * 
 */
Phone.prototype.call = function(number) {
	if(device.platformName == "Android" || device.platformName == "BlackBerry" || window.isSimulator)
		phoneD.call(number);
	else if(device.platformName == "iPhone" && !window.isSimulator)	
		AlopexGap.exec("Phone.call", number);
};

/**
 * SMS보내기 내장 프로그램 실행
 * @param numbers sms 보낼 전화번호
 * 
 */
Phone.prototype.sendSMS = function(numbers) {
	if(device.platformName == "Android" || device.platformName == "BlackBerry" || window.isSimulator) {
		var size = numbers.length;
		var numberStr = "";
		
		for(var i = 0; i < size; i++)
			numberStr += numbers[i] + ";";
		
		log.log(numberStr);
		
		phoneD.sendSMS(numberStr);
	}
	else if(device.platformName == "iPhone" && !window.isSimulator) {
		var size = numbers.length;
		var numberStr = "";
		
		for(var i = 0; i < size; i++) {
			if(i != 0) numberStr += ";"; 
			numberStr += numbers[i];
		}
		log.log(numberStr);
		
		AlopexGap.exec("Phone.sendSMS", numberStr);
	}
};

/**
 * 이메일 보내기 내장 프로그램 실행
 * @param account 이메일 보낼 주소
 * 
 */
Phone.prototype.sendEmail = function(account) {
	if(device.platformName == "Android" || device.platformName == "BlackBerry" || window.isSimulator)
		phoneD.sendEmail(account);
	else if(device.platformName == "iPhone" && !window.isSimulator)
		AlopexGap.exec("Phone.sendEmail", account);
};

var phone;

AlopexGap.addConstructor(function() {
	if(typeof phone == "undefined")
		phone = new Phone();
});

/**
 * Push Service 등 알림 설정하기
 * 
 * 상태표시창과 Badge는 각각 설정할 수 있도록 하고
 *   (향후 다른 플랫폼에서 서로 지원할 가능성이 약간있으므로)
 * 구현할때 platform를 구분하여 화면표시를 바꾸며 해당 설정을 표시/비표시하며
 * 적용되지않는플랫폼 set할 경우 log에 "해당 기능은 iPhone/Android에서 지원되지 않습니다" 출력 
 * @constructor
 */
function Notification() {
	/**
	 * 알림 서비스 사용여부
	 */
//	this.notificationEnable = false;
	/**
	 * 알림 시에 알림창 사용여부
	 */
//	this.alarmEnable = false;
	/**
	 * 알림 시에 소리 사용여부
	 */
//	this.soundEnable = false;
	/**
	 * 알림 시에 Bedge 사용여부(iPhone만 가능)
	 */
//	this.bedgeEnable = false;
	
//	this.TIME_AM_PM = "ampm";
//	this.TIME_HOUR = "hour";
//	this.TIME_MINUTE = "minute";
//	
//	this.OPTION_REPEAT = "repeat";
//	this.OPTION_REPEAT_INTERVAL = "repeat_interval";
	
	this.noticeForAndroid = "해당 기능은 Android 에서 지원되지 않습니다.";
	
	if(device.platformName == "iPhone" && !window.isSimulator)
		AlopexGap.exec("Notification.initNotification");
}

/**
 * 알림 서비스 사용여부 값 
 * 
 */
Notification.prototype.getNotificationEnable = function() {
	if(device.platformName == "Android" || device.platformName == "BlackBerry" || window.isSimulator)
		return notificationD.getNotificationEnable();
	else if(device.platformName == "iPhone" && !window.isSimulator)
		return this.notificationEnable;
};
/**
 * 알림 서비스 사용여부 설정
 * @param enable true이면 사용 false 이면 비사용
 * 
 */
Notification.prototype.setNotificationEnable = function(enable) {
	if(device.platformName == "Android" || device.platformName == "BlackBerry" || window.isSimulator)
		notificationD.setNotificationEnable(enable);
	else if(device.platformName == "iPhone" && !window.isSimulator)
		AlopexGap.exec("Notification.setNotificationEnable", enable);
};

/**
 * 알림 시에 알림창 사용여부 값 
 * 
 */
Notification.prototype.getAlarmEnable = function getAlarmEnable() {
	if(device.platformName == "Android") {
		alert(this.noticeForAndroid);
		log.warn(this.noticeForAndroid);
	}
	else if(device.platformName == "BlackBerry" || window.isSimulator)
		return notificationD.getAlarmEnable();
	else if(device.platformName == "iPhone" && !window.isSimulator)
		return this.alarmEnable;
};
/**
 * 알림 시에 알림창 사용여부 설정
 * @param enable true이면 사용 false 이면 비사용
 * 
 */
Notification.prototype.setAlarmEnable = function(enable) {
	if(device.platformName == "Android") {
		alert(this.noticeForAndroid);
		log.warn(this.noticeForAndroid);
	}
	else if(device.platformName == "BlackBerry" || window.isSimulator)
		notificationD.setAlarmEnable(enable);
	else if(device.platformName == "iPhone" && !window.isSimulator)
		AlopexGap.exec("Notification.setAlarmEnable", enable);
};

/**
 * 알림 시에 Bedge 사용여부 값 
 *  
 */
Notification.prototype.getBadgeEnable = function() {
	if(device.platformName == "Android" || window.isSimulator) {
		alert(this.noticeForAndroid);
		log.warn(this.noticeForAndroid);
	}
	else if (device.platformName == "BlackBerry") {
		notificationD.getBadgeEnable(enable);
	}
	else if(device.platformName == "iPhone" && !window.isSimulator)
		return this.badgeEnable;
};

/**
 * 알림 시에 Bedge 사용여부 설정
 * @param enable true이면 사용 false 이면 비사용
 * 
 */
Notification.prototype.setBadgeEnable = function(enable) {
	if(device.platformName == "Android" || window.isSimulator) {
		alert(this.noticeForAndroid);
		log.warn(this.noticeForAndroid);
	}
	else if (device.platformName == "BlackBerry") {
		notificationD.setBadgeEnable(enable);
	} else if(device.platformName == "iPhone" && !window.isSimulator)
		AlopexGap.exec("Notification.setBadgeEnable", enable);
};

/**
 * 알림 시에 status bar 표시 사용여부 값 
 * 
 */
Notification.prototype.getStatusBarEnable = function() {
	if(device.platformName == "Android" || device.platformName == "BlackBerry" || window.isSimulator)
		notificationD.getStatusBarEnable();
	else if(device.platformName == "iPhone" && !window.isSimulator)
		log.warn("해당 기능은 iPhone에서 지원되지 않습니다.");
};
/**
 * 알림 시에 status bar 표시 사용여부 설정
 * @param enable true이면 사용 false 이면 비사용
 * 
 */
Notification.prototype.setStatusBarEnable = function(enable) {
	if(device.platformName == "Android" || device.platformName == "BlackBerry" || window.isSimulator)
		notificationD.setStatusBarEnable(enable);
	else if(device.platformName == "iPhone" && !window.isSimulator)
		log.warn("해당 기능은 iPhone에서 지원되지 않습니다.");
};

/**
 * 알림 시에 소리 사용여부 값 
 * 
 */
Notification.prototype.getSoundEnable = function() {
	if(device.platformName == "Android" || device.platformName == "BlackBerry" || window.isSimulator)
		notificationD.getSoundEnable();
	else if(device.platformName == "iPhone" && !window.isSimulator)
		return this.soundEnable;
};

/**
 * 알림 시에 울릴 사운드 Ringtone중에서 선택하기
 * - soundId: Ringtone 아이디 Ringtone. getAllRingtone에서 가져온 값 사용.
 * @param enable
 * 
 */
Notification.prototype.setSoundEnable = function(enable) {
	if(device.platformName == "Android" || device.platformName == "BlackBerry" || window.isSimulator)
		notificationD.getSoundEnable(enable);
	else if(device.platformName == "iPhone" && !window.isSimulator)
		AlopexGap.exec("Notification.setSoundEnable", enable);
};

/** 진동설정 */
Notification.prototype.getVibrationEnable = function() {
	if(device.platformName == "Android" || device.platformName == "BlackBerry" || window.isSimulator)
		return notificationD.getVibrationEnable();
	else if(device.platformName == "iPhone" && !window.isSimulator)
		log.warn("해당 기능은 iPhone에서 지원되지 않습니다.");
};
Notification.prototype.setVibrationEnable = function(enable) {
	if(device.platformName == "Android" || device.platformName == "BlackBerry" || window.isSimulator)
		notificationD.setVibrationEnable(enable);
	else if(device.platformName == "iPhone" && !window.isSimulator)
		log.warn("해당 기능은 iPhone에서 지원되지 않습니다.");
};

/** 알림 sound 설정 */
Notification.prototype.getSoundRingtone = function() {
	if(device.platformName == "Android" || window.isSimulator )
		return notificationD.getSoundRingtone();
	else if(device.platformName == "iPhone" || device.platformName == "BlackBerry")
		log.warn("해당 기능은 iPhone에서 지원되지 않습니다.");
	else if(device.platformName == "BlackBerry")
		log.warn("해당 기능은 BlackBerry에서 지원되지 않습니다.");

};

Notification.prototype.setSoundRingtone = function(soundId) {
	if(device.platformName == "Android" || window.isSimulator )
		notificationD.setSoundRingtone(soundId);
	else if(device.platformName == "iPhone" || device.platformName == "BlackBerry")
		log.warn("해당 기능은 iPhone에서 지원되지 않습니다.");
	else if(device.platformName == "BlackBerry")
		log.warn("해당 기능은 BlackBerry에서 지원되지 않습니다.");
};

Notification.prototype.setNotificationCallback = function(callback) {
	if(device.platformName == "Android" || window.isSimulator )
		log.warn("해당 기능은 Android에서 지원되지 않습니다.");
	else if(device.platformName == "BlackBerry")
		log.warn("해당 기능은 BlackBerry에서 지원되지 않습니다.");
	else if(device.platformName == "iPhone" && !window.isSimulator) {
		AlopexGap.exec("Notification.setNotificationCallback", GetFunctionName(callback));
	}
};

//Notification.prototype.requestProvisioning = function(successCallback, errorCallback, userId) {
//	if(device.platformName == "Android") {
//	}
//	else if(device.platformName == "BlackBerry") {
//	}
//	else if(device.platformName == "iPhone")
//		AlopexGap.exec("Notification.requestProvisioning", GetFunctionName(successCallback), GetFunctionName(errorCallback), userId);
//};

/**
 * time 은 JSON 형식으로
 * var time = { "ampm" : "am", "hour" : 10, "minute" : 30 }; 또는
 * var time = {};
 * time["ampm"] = "am";
 * time["hour"] = 10;
 * time["minute"] = 30;
 * 두 가지 표현 방식으로 가능
 * 
 * var options = {
		"url" : "/uidef/controller/navigate/navigate_test.html",	// 필수
		"parameters" : "parameter1=value1&parameter2=value2",
		"repeat" : false,
		"repeat_interval" : 10000,
		"status_bar" : true,
		"status_bar_title" : "Status Bar Title",
		"status_bar_message" : "Status Bar Message Body",
		"vibration" : true,
		"vibration_duration" : 1000,
		"sound" : true,
		"sound_ringtone" : 14	// if there is no notification whose id is 14, it plays default notification ringtone.
	};
 */
Notification.prototype.addNotification = function addNotification(id, time, options) {
	if(time.ampm == undefined || time.hour == undefined || time.minute == undefined) {
		log.error("time object is not correct.");
		
		return;
	}
	
	if(options.url == undefined) {
		log.error("options.url is required.");
		
		return;
	}
	
	var timeStr = JSON.stringify(time);
	var optionStr = JSON.stringify(options);
	
	if(device.platformName == "Android")
		notificationD.addNotification(id, timeStr, optionStr);
	else if(device.platformName == "BlackBerry") {
	}
	else if(device.platformName == "iPhone") {
	}
};

Notification.prototype.removeNotification = function removeNotification(id) {
	if(device.platformName == "Android")
		notificationD.removeNotification(id);
	else if(device.platformName == "BlackBerry") {
	}
	else if(device.platformName == "iPhone") {
	}
};

//Notification.prototype.removeAllNotification = function removeAllNotification() {
//	if(device.platformName == "Android")
//		notificationD.removeAllNotification(JSON.stringify(this.notifications));
//	else if(device.platformName == "BlackBerry") {
//	}
//	else if(device.platformName == "iPhone") {
//	}
//};

var notification;

AlopexGap.addConstructor(function() {
	if(typeof notification == "undefined")
		notification = new Notification();
});

/**
 ****************************************** Ringtone Class ***************************************************
 *		
 */

//ringtones["링톤아이디"] = "링톤이름"; 으로 설정
/**
 * 벨소리 설정에 관련된 클래스
 * @constructor
 */
function Ringtone() {
	this.ringtones = [];
	this.length = 0;
	
	this.callback = null;
}

/** ringtones["링톤아이디"] = "링톤이름"; 으로 설정*/
/** 
 * 링톤 전체 리스트 가져오기 
 * 
 * @param callback 성공적으로 RingTone을 가져왔을 시 호출되는 콜백함수
 * */
 Ringtone.prototype.getAllRingTone = function(callback) {
	if(device.platformName == "Android" || window.isSimulator  )
		ringtoneD.getAllRingTone(GetFunctionName(callback));
	else if(device.platformName == "iPhone" || device.platformName == "BlackBerry") {}
};

var ringtone;

AlopexGap.addConstructor(function() {
	if(typeof ringtone == "undefined")
		ringtone = new Ringtone();
});

/**
 ****************************************** Preference Class ***************************************************
 *		사용자의 설정값을 저장해 놓는 클래스. 어플리케이션의 저장소 역할도 하며 세션정보 같은 것들을 저장해 두고 나중에 읽어올 때도 사용할 수 있다. 
 */

/**
 * Preference 생성자
 * TODO 향후 어플리케이션 외부공유 저장소 => Release v1.0 에는 비포함
 * @constructor
 */
function Preference() {
	if(device.platformName == "iPhone" && !window.isSimulator)
		/**
		 * 설정값들의 목록
		 * @members
		 */
		this.preferences = new Object();
}

/**
 * boolean 형식으로 설정값 저장하기
 * @param key 저장할 키
 * @param value 저장할 값
 * 
 */
Preference.prototype.putBoolean = function (key, value) {
	var bValue = value;
	
	if(typeof value != "boolean") {
		if(value.toLowerCase() == "true")
			bValue = true;
		else if(value.toLowerCase() == "false")
			bValue = false;
		else {
			log.warn("defValue parameter is not a boolean value (" + e + ")");
			
			return;
		}
	}
	
	if(device.platformName == "Android" || device.platformName == "BlackBerry" || window.isSimulator)
		preferenceD.putBoolean(key, bValue);
	else if(device.platformName == "iPhone" && !window.isSimulator) {
		this.preferences[key] = value;
		
		AlopexGap.exec("Preference.put", key, value);
	}
};

/**
 * boolean 형식으로 설정값 가져오기
 * @param key 읽어올 키
 * @param defValue 값이 없을 경우 가져올 기본값
 * 
 */
Preference.prototype.getBoolean = function(key, defValue) {
	var value = defValue;
	
	if(typeof defValue != "boolean") {
		if(defValue.toLowerCase() == "true")
			value = true;
		else if(defValue.toLowerCase() == "false")
			value = false;
		else {
			log.warn("defValue parameter is not a boolean value (" + e + ")");
			
			return;
		}
	}

	if(device.platformName == "Android" || device.platformName == "BlackBerry" || window.isSimulator)
		return preferenceD.getBoolean(key, value);
	else if(device.platformName == "iPhone" && !window.isSimulator) {
		var val = this.preferences[key];
		
		if(val != "undefined" && val != null) {
			if(val == true || val == "true" || val == "yes")
				return true;
			else 
				return false;
		}
		else
			return defValue;
	}
};

/**
 * float 형식으로 설정값 저장하기
 * @param key 저장할 키
 * @param value 저장할 값
 * 
 */
Preference.prototype.putFloat = function(key, value) {
	var fValue = value;
	
	if(typeof value != "number") {
		try {
			fValue = parseFloat(value);
		} catch (e) {
			log.warn("defValue parameter is not a float value (" + e + ")");
			return;
		}
	}
	
	if(device.platformName == "Android" || window.isSimulator)
		preferenceD.putFloat(key, fValue + "");
	else if(device.platformName == "BlackBerry")
		preferenceD.putFloat(key, fValue);
	else if(device.platformName == "iPhone" && !window.isSimulator) {
		this.preferences[key] = value;
		AlopexGap.exec("Preference.put", key, value);
	}
};

/**
 * float 형식으로 설정값 가져오기
 * @param key 읽어올 키
 * @param defValue 값이 없을 경우 가져올 기본값
 * 
 */
Preference.prototype.getFloat = function(key, defValue) {
	var value = defValue;
	
	if(typeof defValue != "number") {
		try {
			value = parseFloat(defValue);
		} catch (e) {
			log.warn("defValue parameter is not a float value (" + e + ")");
			
			return 0.0;	
		}
	}
	
	if(device.platformName == "Android" || window.isSimulator)
		return parseFloat(preferenceD.getFloat(key, value + ""));
	else if(device.platformName == "BlackBerry")
		return parseFloat(preferenceD.getFloat(key, value));
	else if(device.platformName == "iPhone" && !window.isSimulator) {
		var val = this.preferences[key];
		
		if(val != "undefined" && val != null) {
			try {
				return parseFloat(val);
			} catch(err) {
				return defValue;
			}
		}
		else
			return defValue;
	}
};

/**
 * int 형식으로 설정값 저장하기
 * @param key 저장할 키
 * @param value 저장할 값
 * 
 */
Preference.prototype.putInt = function(key, value) {
	var iValue = value;
	
	if(typeof value != "number") {
		try {
			iValue = parseInt(value,10);
		} catch(e) {
			log.warn("defValue parameter is not a integer value (" + e + ")");
			
			return;
		}
	}
	
	if(iValue <= 2147483647 && iValue >= -2147483648) {
		if(device.platformName == "Android" || device.platformName == "BlackBerry" || window.isSimulator)
			preferenceD.putInt(key, iValue);
		else if(device.platformName == "iPhone" && !window.isSimulator) {
			this.preferences[key] = value;
			AlopexGap.exec("Preference.put", key, value);
		}
	}
	else {
		log.warn("Exceeding int range");
		
		return;
	}
};

/**
 * int 형식으로 설정값 가져오기
 * @param key 읽어올 키
 * @param defValue 값이 없을 경우 가져올 기본값
 * 
 */
Preference.prototype.getInt = function(key, defValue) {
	var value = defValue;
	if(typeof defValue != 'number') {
		try {
			value = parseInt(defValue, 10);
		} catch (e) {
			log.warn("defValue parameter is not a integer value ("+e+")");
			return 0;	
		}
	}
	
	if(device.platformName == "Android" || device.platformName == "BlackBerry" || window.isSimulator)
		return preferenceD.getInt(key, value);
	else if(device.platformName == "iPhone" && !window.isSimulator) {
		var val = this.preferences[key];
		if(val != "undefined" && val != null) {
			try {
				return parseInt(val);
			} catch(err) {
				return defValue;
			}
		}
		else {
			return defValue;
		}
	}
};

/**
 * String 형식으로 설정값 저장하기
 * @param key 저장할 키
 * @param value 저장할 값
 * 
 */
Preference.prototype.putString = function(key, value) {
	if(device.platformName == "Android" || device.platformName == "BlackBerry" || window.isSimulator)
		preferenceD.putString(key, value + "");
	else if(device.platformName == "iPhone" && !window.isSimulator) {
		this.preferences[key] = value;
		AlopexGap.exec("Preference.put", key, value);
	}
};

/**
 * String 형식으로 설정값 가져오기
 * @param key 읽어올 키
 * @param defValue 값이 없을 경우 가져올 기본값
 * 
 */
Preference.prototype.getString = function(key, defValue) {
	if(device.platformName == "Android" || device.platformName == "BlackBerry" || window.isSimulator) {
		var str = new String(preferenceD.getString(key, defValue + "")) + "";
		return str;
	}
	else if(device.platformName == "iPhone" && !window.isSimulator) {
		var val = this.preferences[key];
		
		if(val != "undefined" && val != null)
			return val;
		else
			return defValue;
	}
};

var preference;

AlopexGap.addConstructor(function() {
	if(typeof preference == "undefined")
		preference = new Preference();
});






/**
 * 디버깅 등의 정보를 표시하기 위한 클래스. Javascript에서 호출한 log등은 네이티브 플랫폼의 logging과 연동된다. 예를 들면 Android는 logcat 에 출력되고, iPhone은 debugging 창에 표시된다.
 * @constructor
 */
function Log() {
	/**
	 * 로그를 표시할 지 여부
	 * @members
	 */
	this.show = true;
}

/**
 * log 수준으로 출력
 * @param message 출력할 메시지
 * 
 */
Log.prototype.log = function(message) {
	if(!this.show)
		return;
	
	message += "";
	
	if(device.platformName == "Android" || window.isSimulator || device.platformName == "BlackBerry")
		logD.log(message + "");
	else if(device.platformName == "iPhone" && !window.isSimulator) {
		if(AlopexGap.available)
			AlopexGap.exec('DebugConsole.log', message, {logLevel: 'INFO'});
	}
	else
		console.log(message);
};

/**
 * warn 수준으로 출력
 * @param message 출력할 메시지
 * 
 */
Log.prototype.warn = function(message) {
	if(!this.show)
		return;
	
	if(device.platformName == "Android" || window.isSimulator || device.platformName == "BlackBerry")
		logD.warn(message + "");
	else if(device.platformName == "iPhone" && !window.isSimulator) {
		if(AlopexGap.available)
			AlopexGap.exec('DebugConsole.log', message, {logLevel: 'WARN'});
	}
	else
		console.error(message);
};

/**
 * error 수준으로 출력
 * @param message 출력할 메시지
 * 
 */
Log.prototype.error = function(message) {
	if(!this.show)
		return;
	
	if(device.platformName == "Android" || window.isSimulator || device.platformName == "BlackBerry")
		logD.error(message + ""); 
	else if(device.platformName == "iPhone" && !window.isSimulator) {
		if(AlopexGap.available)
			AlopexGap.exec('DebugConsole.log', message, {logLevel: 'ERROR'});
	}
	else
		console.error(message);
};

var log;

AlopexGap.addConstructor(function() {
	if(typeof log == "undefined")
		log = new Log();
});

/**
 * 0.6.1a Added feature
 * */
/**
 * 여러 어플리케이션이 같이 공유할 수 있는 global preference 저장소.
 * @constructor
 */
function GlobalPreference() {
	if(device.platformName == "iPhone" && !window.isSimulator)
		this.preferences = new Object();
}

/**
 * boolean 타입 데이터 가져오기
 * @param key 키 값
 * @param defValue 값이 존재하지 않을 시 리턴되는 default 값
 * @return boolean 키 값에 해당하는 값, 없을시 defValue
 */
GlobalPreference.prototype.getBoolean = function(key, defValue) {
	var value = defValue;
	
	if(typeof defValue != "boolean") {
		if(defValue.toLowerCase() == "true")
			value = true;
		else if(defValue.toLowerCase() == "false")
			value = false;
		else {
			log.warn("defValue parameter is not a boolean value (" + e + ")");
			
			return;
		}
	}
	
	if(device.platformName == "Android" || window.isSimulator)
		return globalPreferenceD.getBoolean(key, value);
	else if(device.platformName == "BlackBerry")
		return preferenceD.getBoolean(key, value);
	else if(device.platformName == "iPhone" && !window.isSimulator) {
		var val = this.preferences[key];
		if(val != "undefined" && val != null) {
			if(val == true || val == "true" || val == "yes")
				return true;
			else 
				return false;
		}
		else
			return defValue;
	}
};

/**
 * float 타입 데이터 가져오기
 * @param key 키 값
 * @param defValue 값이 존재하지 않을 시 리턴되는 default 값
 * @return float 키 값에 해당하는 값, 없을시 defValue
 *  */
GlobalPreference.prototype.getFloat = function(key, defValue) {
	var value = defValue;
	
	if(typeof defValue != 'number') {
		try {
			value = parseFloat(defValue);
		} catch (e) {
			log.warn("defValue parameter is not a float value ("+e+")");
			return 0.0;	
		}
	}
	
	if(device.platformName == "Android" || window.isSimulator)
		return globalPreferenceD.getFloat(key, value);
	else if(device.platformName == "BlackBerry")
		return preferenceD.getFloat(key, value);
	else if(device.platformName == "iPhone" && !window.isSimulator) {
		var val = this.preferences[key];
		if(val != "undefined" && val != null) {
			try {
				return parseFloat(val);
			} catch(err) {
				return defValue;
			}
		}
		else
			return defValue;
	}
};

/**
 * int 타입 데이터 가져오기
 * @param key 키 값
 * @param defValue 값이 존재하지 않을 시 리턴되는 default 값
 * @return int 키 값에 해당하는 값, 없을시 defValue
 */
GlobalPreference.prototype.getInt = function(key, defValue) {
	var value = defValue;
	
	if(typeof defValue != 'number') {
		try {
			value = parseInt(defValue);
		} catch (e) {
			log.warn("defValue parameter is not a integer value ("+e+")");
			return 0;	
		}
	}
	
	if(device.platformName == "Android" || window.isSimulator)
		return globalPreferenceD.getInt(key, value);
	else if(device.platformName == "BlackBerry")
		return preferenceD.getInt(key, value);
	else if(device.platformName == "iPhone" && !window.isSimulator) {
		var val = this.preferences[key];
		if(val != "undefined" && val != null) {
			try {
				return parseInt(val);
			} catch(err) {
				return defValue;
			}
		}
		else {
			return defValue;
		}
	}
};

/**
 * string 타입 데이터 가져오기
 * @param key 키 값
 * @param defValue 값이 존재하지 않을 시 리턴되는 default 값
 * @return string 키 값에 해당하는 값, 없을시 defValue
 *  */
GlobalPreference.prototype.getString = function(key, defValue) {
	if(typeof defValue != "string") {
		log.warn("defValue parameter is not a string value");
		return "";
	}
	
	if(device.platformName == "Android" || window.isSimulator)
		return globalPreferenceD.getString(key, defValue);
	else if(device.platformName == "BlackBerry") {
		var str = new String(preferenceD.getString(key, defValue)) + "";
		
		return str;
	}
	else if(device.platformName == "iPhone" && !window.isSimulator) {
		var val = this.preferences[key];
		
		if(val != "undefined" && val != null)
			return val;
		else
			return defValue;
	}
};

/**
 * boolean 타입 데이터 저장
 * @param key 값을 찾을 시 사용될 키 값
 * @param value boolean 타입 데이터
 */
GlobalPreference.prototype.putBoolean = function(key, value) {
	var bValue = value;
	
	if(typeof value != "boolean") {
		if(value.toLowerCase() == "true")
			bValue = true;
		else if(value.toLowerCase() == "false")
			bValue = false;
		else {
			log.warn("defValue parameter is not a boolean value (" + e + ")");
			
			return;
		}
	}
	
	if(device.platformName == "Android" || window.isSimulator)
		globalPreferenceD.putBoolean(key, bValue);
	else if(device.platformName == "BlackBerry")
		preferenceD.putBoolean(key, bValue);
	else if(device.platformName == "iPhone" && !window.isSimulator) {
		this.preferences[key] = bValue;
		AlopexGap.exec("GlobalPreference.put", key, bValue);
	}
};
/**
 * float 타입 데이터 저장
 * @param key 값을 찾을 시 사용될 키 값
 * @param value float 타입 데이터
 */
GlobalPreference.prototype.putFloat = function(key, value) {
	var fValue = value;
	
	if(typeof value != 'number') {
		try {
			fValue = parseFloat(value);
		} catch (e) {
			log.warn("defValue parameter is not a float value ("+e+")");
			return;
		}
	}
	
	if(device.platformName == "Android" || window.isSimulator)
		globalPreferenceD.putFloat(key, fValue);
	else if(device.platformName == "BlackBerry")
		preferenceD.putFloat(key, fValue);
	else if(device.platformName == "iPhone" && !window.isSimulator) {
		this.preferences[key] = fValue;
		AlopexGap.exec("GlobalPreference.put", key, fValue);
	}
};
/**
 * int 타입 데이터 저장
 * @param key 값을 찾을 시 사용될 키 값
 * @param value int 타입 데이터
 */
GlobalPreference.prototype.putInt = function(key, value) {
	var iValue = value;
	
	if(typeof value != "number") {
		try {
			iValue = parseInt(value,10);
		} catch(e) {
			log.warn("defValue parameter is not a integer value (" + e + ")");
			
			return;
		}
	}
	
	if(iValue <= 2147483647 && iValue >= -2147483648) {
		if(device.platformName == "Android" || device.platformName == "BlackBerry" || window.isSimulator)
			preferenceD.putInt(key, iValue);
		else if(device.platformName == "iPhone" && !window.isSimulator) {
			this.preferences[key] = value;
			AlopexGap.exec("Preference.put", key, value);
		}
	}
	else {
		log.warn("Exceeding int range");
		
		return;
	}
	
	if(iValue <= 2147483647 && iValue >= -2147483648) {
		if(device.platformName == "Android" || window.isSimulator)
			globalPreferenceD.putInt(key, iValue);
		else if(device.platformName == "BlackBerry")
			preferenceD.putInt(key, iValue);
		else if(device.platformName == "iPhone" && !window.isSimulator) {
			this.preferences[key] = iValue;
			AlopexGap.exec("GlobalPreference.put", key, iValue);
		}
	}
	else {
		log.warn("Exceeding int range");
		
		return;
	}
};
/**
 * string 타입 데이터 저장
 * @param key 값을 찾을 시 사용될 키 값
 * @param value string 타입 데이터
 */
GlobalPreference.prototype.putString = function(key, value) {
	if(typeof value != "string") {
		log.warn("value parameter is not a string value");
		
		return;
	}
	
	if(device.platformName == "Android" || window.isSimulator)
		globalPreferenceD.putString(key, value);
	else if(device.platformName == "BlackBerry")
		preferenceD.putString(key, value);
	else if(device.platformName == "iPhone" && !window.isSimulator) {
		this.preferences[key] = value;
		AlopexGap.exec("GlobalPreference.put", key, value);
	}
};

GlobalPreference.prototype.setRepository = function(name) {
	if(device.platformName == "Android" || window.isSimulator )
		globalPreferenceD.setRepository(name);
	else if(device.platformName == "BlackBerry")
		preferenceD.setRepository(name);
	else if(device.platformName == "iPhone" && !window.isSimulator) {
		AlopexGap.exec("GlobalPreference.setRepository", name);
	}
};

var globalPreference;

AlopexGap.addConstructor(function() {
	if(typeof globalPreference == "undefined")
		globalPreference = new GlobalPreference();
});

function GeoLocation() {
	this.LATITUDE = "latitude";
	this.LONGITUDE = "longitude";
	this.ACCURACY = "accuracy";
	
	// latitude and longitude are double type variable from platform
	this.lastLocation = [];	//location['latitude'], location['longitude'], location['accuracy']
};

GeoLocation.prototype.getLastLocation = function() {
	return this.lastLocation;
};

/**
 * 반복해서 위치를 가져옴
 * @param successCallback
 * 		callbackFunctionName(location); 
 * 		location['latitude'], location['longitude'], location['accuracy']
 * @param errorCallback 
 * 		callbackFunctionName(String errorMessage);
 * @param options
 * @return void
 */
GeoLocation.prototype.start = function(options, successCallback, errorCallback) {
	if(device.platformName == "Android" || window.isSimulator) {
//		if(options != null) {
//			var optionQuery = [];
//			
//			for(var name in options) {
//				if(options[name] != "" && options[name] != "null" && options[name] != null && options[name] != undefined && options[name] != "undefined")
//					optionQuery.push(name + "=" + options[name]);
//			}
//			
//			geoLocationD.start(optionQuery.join("&"), GetFunctionName(successCallback), GetFunctionName(errorCallback));
//		}
//		else
//			geoLocationD.start(null, GetFunctionName(successCallback), GetFunctionName(errorCallback));
		geoLocationD.start(null, GetFunctionName(successCallback), GetFunctionName(errorCallback));
	}
	else if(device.platformName == "BlackBerry") {
		if(options != null) {
			var optionQuery = [];
			
			for(var name in options) {
				if(options[name] != "" && options[name] != "null" && options[name] != null && options[name] != undefined && options[name] != "undefined")
					optionQuery.push(name + "=" + options[name]);
			}
			
			featureD.startGeoLocation(optionQuery.join("&"), GetFunctionName(successCallback), GetFunctionName(errorCallback));
		}
		else
			featureD.startGeoLocation(GetFunctionName(successCallback), GetFunctionName(errorCallback));

	}
	else if(device.platformName == "iPhone" && !window.isSimulator) {
		AlopexGap.exec("GeoLocation.start", options, GetFunctionName(successCallback), GetFunctionName(errorCallback));
	}
};

/**
 * 한번만 위치를 가져옴. stop 호출 필요 없음
 * startOnce는 옶션에서 정확도만 필요하다고 봄
 * 1.0 버전에서는 옵션은 없음.
 */
GeoLocation.prototype.startOnce = function(options, successCallback, errorCallback) {
	if(device.platformName == "Android" || window.isSimulator) {
//		if(options != null) {
//			var optionQuery = [];
//			
//			for(var name in options) {
//				if(options[name] != "" && options[name] != "null" && options[name] != null && options[name] != undefined && options[name] != "undefined")
//					optionQuery.push(name + "=" + options[name]);
//			}
//			
//			geoLocationD.startOnce(optionQuery.join("&"), GetFunctionName(successCallback), GetFunctionName(errorCallback));
//		}
//		else
//			geoLocationD.startOnce(null, GetFunctionName(successCallback), GetFunctionName(errorCallback));
		geoLocationD.startOnce(null, GetFunctionName(successCallback), GetFunctionName(errorCallback));
	}
	else if(device.platformName == "BlackBerry") {
		if(options != null) {
			var optionQuery = [];
			
			for(var name in options) {
				if(options[name] != "" && options[name] != "null" && options[name] != null && options[name] != undefined && options[name] != "undefined")
					optionQuery.push(name + "=" + options[name]);
			}
			
			featureD.startGeoLocationOnce(optionQuery.join("&"), GetFunctionName(successCallback), GetFunctionName(errorCallback));
		}
		else
			featureD.startGeoLocationOnce(GetFunctionName(successCallback), GetFunctionName(errorCallback));
	}
	else if(device.platformName == "iPhone" && !window.isSimulator) {
		AlopexGap.exec("GeoLocation.startOnce", options, GetFunctionName(successCallback), GetFunctionName(errorCallback));
	}
};

/**
 * 위치가져오기 정지. start로 시작한 경우에는 종료시 반드시 호출
 * @return
 */
GeoLocation.prototype.stop = function() {
	if(device.platformName == "Android" || window.isSimulator)
		geoLocationD.stop();
	else if(device.platformName == "BlackBerry") {
		featureD.stopGeoLocation();
	}
	else if(device.platformName == "iPhone" && !window.isSimulator) {
		AlopexGap.exec("GeoLocation.stop", options, GetFunctionName(successCallback), GetFunctionName(errorCallback));
	}
};

var geoLocation;

AlopexGap.addConstructor(function() {
	if(typeof geoLocation == "undefined")
		geoLocation = new GeoLocation();
});

/**
 * 카메라의 기능을 제공하는 클래스 입니다.
 * 
 * @constructor
 */
function Camera() {
	this.EXTRA_HEIGHT = "height";
	this.EXTRA_WIDTH = "width";
}

/**
 * 사진을 찍고 이미지를 저장한 후 이미지 경로를 반환합니다.
 * @param successCallback 
 * 		callbackFunctionName(String pictureLocation, extra);
 * 		extra['height']. extra['width']; 
 * @param errorCallback 
 * 		callbackFunctionName(String errorMessage);
 * @param options 현재는 없고 향후 활용
 * @return void
 */
Camera.prototype.takePicture = function(options, successCallback, errorCallback) {
	if(device.platformName == "Android" || window.isSimulator)
		cameraD.takePicture(options, GetFunctionName(successCallback), GetFunctionName(errorCallback));
	else if(device.platformName == "BlackBerry") {
		featureD.takePicture(GetFunctionName(successCallback), GetFunctionName(errorCallback));
	}
	else if(device.platformName == "iPhone" && !window.isSimulator) {
		AlopexGap.exec("Camera.takePicture", options, GetFunctionName(successCallback), GetFunctionName(errorCallback));
	}
};

var camera;

AlopexGap.addConstructor(function() {
	if(typeof camera == "undefined")
		camera = new Camera();
});

/**
 * 모바일 디바이스에 있는 센서를 관리하는 클래스입니다.
 * 
 * @constructor
 */
function Sensor() {
	this.TYPE_ACCELEROMETER = "accelerometer";
	this.TYPE_COMPASS = "compass";
}

/**
* 반복해서 센서값을 가져옵니다.
* @param type String 값으로 sensor type = [accelerometer | compass]
* @param options reverved
*/
Sensor.prototype.start = function(type, options, successCallback, errorCallback) {
	if(type != this.TYPE_ACCELEROMETER && type != this.TYPE_COMPASS) {
		errorCallback("Wrong sensor type");
		
		return;
	}
	
	if(device.platformName == "Android" || window.isSimulator )
		sensorD.start(type, GetFunctionName(successCallback), GetFunctionName(errorCallback));
	else if(device.platformName == "BlackBerry") {
		sensorD.start(type, GetFunctionName(successCallback), GetFunctionName(errorCallback));
	}
	else if(device.platformName == "iPhone" && !window.isSimulator) {
	}
};

/**
* 1회 센서값을 가져옵니다.
* @param type String 값으로 sensor type = [accelerometer | compass]
* @param interval int ms값
* @param options reverved
*/
Sensor.prototype.startOnce = function(type, options, successCallback, errorCallback) {
	if(type != this.TYPE_ACCELEROMETER && type != this.TYPE_COMPASS) {
		errorCallback("Wrong sensor type");
		
		return;
	}
	
	if(device.platformName == "Android" || window.isSimulator )
		sensorD.startOnce(type, GetFunctionName(successCallback), GetFunctionName(errorCallback));
	else if(device.platformName == "BlackBerry") {
		sensorD.startOnce(type, GetFunctionName(successCallback), GetFunctionName(errorCallback));
	}
	else if(device.platformName == "iPhone" && !window.isSimulator) {
	}
};

/**
* 해당 Sensor 정지합니다.
* @param type String 값으로 sensor type = [accelerometer | compass]
*/
Sensor.prototype.stop = function(type) {
	if(type != this.TYPE_ACCELEROMETER && type != this.TYPE_COMPASS) {
		errorCallback("Wrong sensor type");
		
		return;
	}
	
	if(device.platformName == "Android" || window.isSimulator )
		sensorD.stop(type);
	else if(device.platformName == "BlackBerry") {
		sensorD.stop(type);
	}
	else if(device.platformName == "iPhone" && !window.isSimulator) {
	}
};

/**
* 모든 Sensor를  정지합니다.
* @param type String 값으로 sensor type = [accelerometer | compass]
*/
Sensor.prototype.stopAll = function() {
	if(device.platformName == "Android" || window.isSimulator )
		sensorD.stopAll();
	else if(device.platformName == "BlackBerry") {
		sensorD.stopAll();
	}
	else if(device.platformName == "iPhone" && !window.isSimulator) {
	}
};

var sensor;

AlopexGap.addConstructor(function() {
	if(typeof sensor == "undefined")
		sensor = new Sensor();
});